2010/03/03

おぉ!GoogleMapAPIのFlex用ライブラリーがswc形式でGoogle本家にあがってます(^_^)/ これで、わざわざFlashとJavaScriptの連携しなくてもよさげ? 3分クッキングで作成してみた。

■google_map.swf htmlTextは機能ダメダメだけど、imgタグでswfを直で読めるんだぁ・・・ (^_^)つ ペタッ まだクラスの中身を詳しく見てないけど、swf間で通信(LocalConnection等)を実装すれば色んなことできそうです。

■Google Maps API for Flash - FlexBuilder ▽チュートリアル http://code.google.com/intl/ja/apis/maps/documentation/flash/tutorial-flexbuilder.html

▽ダウンロード http://maps.googleapis.com/maps/flash/release/sdk.zip

■Maps API キーの取得 ドメイン毎にMapsAPIキーを生成できます。 http://code.google.com/intl/ja/apis/maps/signup.html ドメイン毎に発行なので、開発環境と本番ではキーを別々にしなければいけません。

プログラムは、クラス実装さえわかれば難しいことはなさげです。 「ARK-Web」にわかりやすくまとめられています。 実践編ではFlexとJavaScript連携でやってますが、Flexオンリーでやった方が軽そうだけど、 HTML派に考慮しての事かと思います。

■動作確認サンプル ▽ソース これだけで、あっさり表示されます。 [as3] import com.google.maps.controls.ZoomControl; import com.google.maps.controls.MapTypeControl; import com.google.maps.controls.PositionControl; import com.google.maps.LatLng; import com.google.maps.Map; import com.google.maps.MapEvent; import com.google.maps.MapType;

private var map:Map;
private var locateX:Number = 35.728912;
private var locateY:Number = 139.7095082;

private function onInitialize(event:Event):void {
    map = new Map();
    map.key = GoogleMapキー;
    map.addEventListener(MapEvent.MAP_READY, onMapReady);
    mapContainer.addChild(map);
}

private function onResize(event:Event):void {
    map.setSize(new Point(mapContainer.width, mapContainer.height));        
}

private function onMapReady(event:Event):void {
    map.setCenter(new LatLng(locateX, locateY), 14, MapType.NORMAL_MAP_TYPE);
    map.addControl(new ZoomControl());
    map.addControl(new PositionControl());
    map.addControl(new MapTypeControl());
}

[/as3] locateX、locateYの位置指定は、GoogleMapのパラメータを直接埋め込んでますが、 各パラメータをGoogleからシームレスにやり取りできるかですね。 只今、このサイトと連動できるよう作成中で、何だか面白くなってきました。

  2010/03/01

がちょーん!!FlashCSだけに「FlvPlayback」等の便利なVideoコンポーネントがあるw Flexにないコンポーネントってあるんだねぇ(^_^;) どうりで最近動画プレイヤーが出回ってると思ったら・・・。

■FlashのVideoコンポーネント(Flexには標準で未実装) ビデオプレイヤーの再生・停止は勿論、シークやボリューム等もGUIだけで作れちゃうん。 これならデザイナーさんには重宝されますなぁ(^_^) とは言っても、外部ビデオファイル取得とか他とのマッシュアップとかの処理は、結局ガリガリかかないといけないが・・・。

しかし、こんな便利なもんあるなら俺もFlashで作ろうか?と。 けど「fl.video」パッケージを探せば何とかなるんじゃね?と調べたら、ありました!

■Adobe Flash Media Server productivity tool FMS用のツールなんだけど、Flexでも使えそうです。 Adobe本家から「Adobe Flash Media Server productivity tool」をダウンロードできます。

https://www.adobe.com/cfusion/entitlement/index.cfm?event=custom&sku=FS0000503&e=fms35

FMS用のツールで、他にもやら面白げなライブラリーがある。

「Dynamic Streaming Class」って何?何?これ??(^_^) もしかして動的にAS書き出せちゃうのか???(違うか。。。)

とりあえず後回しで「FLVPlayback2.5」を使ってみる。                 サンプルでスキンもswfで用意されている。 欲を言えば、スキンはswfでなくてas + 素材で欲しかったなぁ。 FlashCSみたくカスタムコンポーネント化すれば、もっと便利かも

■サンプルソース [as3] private function playTopVideo():void { var video:FLVPlayback = new FLVPlayback(); var ui:UIComponent = new UIComponent(); view.topVideo.addChild(ui); ui.addChild( video ); video.width = 320; video.height = 240; video.source = "movie/empire.mp4"; video.skinBackgroundColor = 0x666666; video.skin = "swf/FLVPlaybackSkins/SkinUnderAll.swf"; video.scaleMode = VideoScaleMode.MAINTAIN_ASPECT_RATIO; video.skinAutoHide = false; } [/as3]

  2010/02/25

かなり煩雑なコードになってきたので、クラス化と言う名のリファクタリング。 意地でもPEARや他のライブラリは使わないぞw

■修正内容 VoiceService ver0.2 (1) MixiVoice、Twitterクラス化・ファイル整理

VoiceService | getVoices() | MixiVoice --> HTTPService Twitter --> HTTPService

(2) HTTPサービスクラス「HTTPService」作成 「HTTPRequestService」の命名の方が正しいかも!?

(3) 同時投稿機能追加 とり合えず最低限の実装 ・Twitterは、Basic認証でなくてtokenにするのが今後の課題 ・Mixiは、htmlパースとログイン処理が課題

■VoiceService(抜粋) ファイル分離して非常にわかりやすくなったv(^_^)v

    /**
     * mixi & Twitterボイス取得
     **/
    public function getVoices()
    {
        $mixi_voice = new MixiVoice();
        $voices['mixi'] = $mixi_voice->getVoices();

        $twitter = new Twitter();
        $voices['twitter'] = $twitter->getUserTimeline();

        $results = $this->_marge_voices($voices);
        dump($results);
        return $results;
    }

    /**
     * mixi & Twitterボイス同時投稿
     **/
    public function postVoice($values)
    {
        if ($values->message && $values->password == VOICE_PASSWORD) {
            $mixi_voice = new MixiVoice();
            $is_mixi = $mixi_voice->postMessage($values->message);

            $twitter = new Twitter();
            $is_twitter = $twitter->postMessage($values->message);

            return ($is_mixi && $is_twitter);
        }
    }

※「$this->_marge_voices($voices)」は、MixiVoiceとTwitterデータをマージしてJSON化してる

■MixiVoice(抜粋) 「HTTPService->request」を実装して、paramsをオブジェクトで渡すようにした。 とりあえず、こんなもんかな?

    /**
     * mixiボイス取得
     **/
    public function getVoices()
    {
        $this->login();

        $params->url = MIXI_ECHO_LIST_URL;
        $params->method = 'POST';

        $html = $this->request($params);
        $results = $this->parseVoice($html);
        return json_encode($results);
    }

■Twitter(抜粋) このクラス名だと、また膨大になりそうな予感だけど。。。 これもパラメータをオブジェクトで渡すようにした。

    /**
     * Twitter投稿
     **/
    public function postMessage($message)
    {
        if (!$message) return;

        $posts['status'] = $message;

        $params->posts = $posts;
        $params->url = TWITTER_UPDATE_JSON_URL;
        $params->basic->id = TWITTER_USER_NAME;
        $params->basic->password = TWITTER_PASS;

        $results = $this->curlRequest($params);
        return $results;
    }

■HTTPService(抜粋) これが肝のクラス。 なので、頭が整理できてなずサッパリ(T_T)

cokkie処理やBasic認証が両立できなくて、とりあえず「curl」と「file_get_contents」の併用です。

▽各メリット ・curl:細かいことができそうで速い ・file_get_contents:ソースが短くできそう

最終的にはcurlで統一するかな?

    /**
     * HTTPリクエスト(curl)
     **/
    public function curlRequest($params)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $params->url);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 2);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

        //POST
        if ($params->posts) {
            $posts = http_build_query($params->posts, '', '&');
            curl_setopt($ch, CURLOPT_POST, 1);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $posts);
        }

        //cookies
        //TODO 
        //curl_setopt($ch, CURLOPT_COOKIEJAR, "cookie");

        //BASIC認証
        if ($params->basic) {
            curl_setopt($ch, CURLOPT_USERPWD, "{$params->basic->id}:{$params->basic->password}");
            dump($params->basic);
        }
        $results = curl_exec($ch);
        curl_close($ch);
        return $results;
    }

    /**
     * HTTPリクエスト(file_get_contents)
     **/
    public function request($params) {
        $headers[] = 'Content-Type: application/x-www-form-urlencoded';

        if (is_array($params->posts)) {
            $content = http_build_query($params->posts, '', '&');
            $content_length = strlen($content);
            $headers[] = "Content-Length: {$content_length}";
            $requests['http']['content'] = $content;
        }

        //Basic認証
        if ($params->basic) {
            $basic = base64_encode("{$params->basic->id}:{$params->basic->password}");
            $header[] = "Authorization: Basic ".$basic;
        }

        //cokkie
        //TODO paramsかセッションにする?
        if ($this->cookie) {
            $headers[] = "Cookie: {$this->cookie}";
        }

        if ($params->method) {
            $method = $params->method;
        } else {
            $method = 'GET';
        }
        $requests['http']['method'] = $method;
        $requests['http']['header'] = implode("\r\n", $headers);

        $context = stream_context_create($requests);
        $contents = file_get_contents($params->url, false, $context);

        //cookie取得・設定
        if ($http_response_header) {
            $this->setCookieForHttpResponseHeader($http_response_header);
        }
        return $contents;
    }

※「$this->setCookieForHttpResponseHeader」は、HTTPヘッダーをパース

  2010/02/24

FlashのhtmlTextの機能、何とかならんかね~>Adobe せめて画像の回り込みぐらい(T_T)

さて、Androido本を買ってみた(もち会社経費でw)。

「Google Androidプログラミング入門 (大型本)」

豆蔵社員が作ってて、本質的な基礎部分に触れていて結構わかりやすいと思う。

出版不況とは言えども、こう言う専門書籍とかは手に持ってみたい感じがする。

ざっと見た感じ、

(1) ファイル構成 (2) Actibity、イベント (3) Intentによるデータ管理

この辺の概念を抑えればとり合えずアプリは作れそうだ。 サンプルアプリ作ってみたけど、結構わかりやすいと思う。

とは言っても、コンポーネントやサービスが膨大っぽいし、実機を持ってないからなぁ・・・。 なんかAndroidの実機が欲しくなってきたこの頃(^^)

■個人的感想 ・Javaベースなので入りやすい →iPhone SDKみたく「Objective-C」覚えなくて良い

・思想がMVCっぽくて、階層がわかりやすい →人によって作り方が大きく変わることがない感じ  これは重要

・XMLの定義は、FlexのMXMLと基本概念は同じ →UIベースで定義できるのでスピーディー  ただ、第一印象では機能的に物足りない感(機能を知らないだけかも知れんが)

・データバインディングが面倒くさい感  →ソースベースでしかできないのかな?  「WebObjects」や「iPhone SDK」のInterfaceBuilder機能が搭載されれば、かなりスピーディーになると思う

・「自動ビルド」に設定しておくと、ビルドエラーが多発  →原因調べないと・・・

・イベント監視が面倒くさそう  →モバイルフォンだから仕方ないが・・・

  2010/02/18

何か勉強してる時間がない。。。 と言い訳はしたくないから、無理にでもやるw

まずは環境整備から。 「Android SDK + Eclipse ADT」で構築してみる。

とりあえず、「Android Developers」を見ながらインストール。 ちょうど「Android 2.1 API Level 7」がリリースされてた。 そもそも、Ver1.xから何が違うのかすらわからない状態だが(笑)

基本は、 (1) SDKのパスとおして (2) Eclipse Plugin入れて (3) EclipseでSDK Componentsをインストール

自宅はMac、会社ではWindows版を。

自分メモ ■SDK (1) ダウンロード android-sdk_r04-windows.zip

(2) インストール先はC直下にした。 C:\air2_b1_sdk_win_111709

(3) toolsへのPath追加 C:\android-sdk-windows\tools

■ADT Plugin for Eclipse - 設定マニュアル http://developer.android.com/sdk/eclipse-adt.html

(1) Eclipse 3.4 (Ganymede)なので、以下のインストールURL https://dl-ssl.google.com/android/eclipse/

(2) ウィンドウ > 設定 > Androido (3) SDKロケーション設定して【適用】

C:\android-sdk-windows

この時点で、パッケージはインストールされてなかったので、

(4) ウィンドウ > Android SDK and AVD Manager > Avalible Pakages (5) パッケージを選択して【Install Selected】 ちょい時間がかかる。 全部入れる必要はなかったかな?w (6) Virtual Devicesもとり合えず設定

■動作確認でプロジェクト作成 基本は通常のプロジェクト作成と同じ

(1) ファイル > 新規 > Androidプロジェクト (2) 各項目設定 - BuildTarget:とり合えず最新の2.1(API Level7)を選択 - アプリケーション名:Hello - パッケージ:jp.co.telepath(任意) - Create Activity:Activityを継承するクラス名 ※Activity = Androidアプリ画面 Androidアプリ作成の基本“Activity”とは何か?

(3)【完了】

で、ここでBuildエラーw Eclipseで自動ビルドにしておくと、genがうまく作成されないらしい(ホント?) なんで、

■genのクリーンアップ (1)「自動的にビルド」のチェック外す (2) genディレクトリ削除 (3) プロジェクト > クリーン 一応、コンパイルされた。

■確認 (1) HelloWorld的なw [java] package jp.co.telepath;

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

public class Hello extends Activity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); TextView tv = new TextView(this); tv.setText("OKOKOK"); setContentView(tv); }

} [/java]

onCreateはイベントハンドラっぽいな。 Activityの状態遷移に記載されてるのが全てなのかな? 何かイベント管理が大変そうだけど。。。 その前にActivityクラス等のソース見れるようにしないとw

(2) 実行 バーチャル携帯の起動遅い・・・結構ストレスかもw

てな訳で次は、まずAndoroidの基礎知識から!

  2010/02/08

iPhoneがFlashを載せない理由

Flashはバギーだし、HTML5で十分

やっとRIAが業界全体が動き始めた実感。
「Flash vs HTML5」って文字を良く見るけど、個人的にはどっちでも同じかなぁ?と思う。
どっちを選択しようと、デベロッパ的にはやる事は変わらないと思う。

問題は、FlashであろうとHTML5であろうと、デザイナーとデベロッパの境界線が更にグレーになる。
個人的には、FlashもHTML5(JS・CSS含む)もWebデザイナーで全部作ってくれと言いたいが・・・
多分、この中間層の人材需要が増えるんじゃないかな?と思う。
さて、HTML5優位とはいいつつ、現状はFlashに劣っている部分は否めないと思う。

■現状のHTML5 + JSの問題点・疑問点

(1) ブラウザ依存しすぎ  これが一番懸念されてることすよね。
(2) ライブラリが規格統一されてない jQuery、PrototypeJs、YUIと選択肢が多すぎてこの先どうなるのか?
(3) 開発標準環境が確立されてない  これはまだ仕方ないけど、時間短縮は開発ツールが命だからねえ。  JSに関してはせめてヒエラルキーを追えるツール探さなきゃ(Eclipse Pluginとかあるのかな?)
(4) 既にActionScript3.2で実現可能

JSでしかできない秀逸な機能が今のところ見当たらない FlashPlayer10.1 & Air2.0はかなり面白いのだが、どうなるのかなぁ? どちらにしろHTML5、JSのクラス実装くらいは把握しておかないと死ねる。 あとAndroido、XCodeは手をつけておかないと。

  2010/02/06

PHPライブラリは誰かの「twitter2mixivoice.php」もあったけど、

(1) PEAR依存 (2) 自前だと修正・拡張ができる

なんで、ライブラリも自前で。

■問題点 (1) mixiボイスのAPIがない →よって、無理矢理ログインしてHTMLパース以外方法なし

(2) クロスドメイン制限 →swfで直接通信が理想なんだけど、mixiもtwitterもクロスドメイン制限があるので断念  サーバかまして処理する事に

■主なポイント (1) AMF通信 →高速かつFlexとオブジェクトの親和性が高いAMFを採用  JSON、XML変換できるけど、今は必要なし  てか、XMLって遅いし面倒だし通信においてメリットあるのか?といつも疑問に思う。

(2) データのマージ  twitterはJSON、mixiはテキスト取得して日付ソートしながらデータマージ  (超暫定で最低限のタイトルと日付だけ)

とりあえずデータ取得&マージまで作ったので、あとはマルチ投稿の仕様考える。 ある程度まとったら機能毎にクラス化へ。

途中までのソース うーん、デザイン的にコードは別途コンポーネント作った方がいいなw swf側ソースは、色々ネタが多いので別途記事にする予定(?)

■VoiceService.php

require_once 'Service.php';

class VoiceService extends Service {

    /**
     * データ取得
     **/
    public function getVoices() {
        $voices['mixi'] = $this->mixi_voices();
        $voices['twitter'] = $this->twitter_user_timeline();
        $results = $this->_marge_voices($voices);
        return $results;
    }

    /**
     * Twitterタイムライン取得
     **/
    private function twitter_user_timeline()
    {
        $this->_twitter_auth();
        $url = "http://twitter.com/statuses/user_timeline/{$this->twitter_user_name}.json";
        $url.= "?since=".urlencode(date('D, d M Y G:i:s GMT', strtotime('-10 day')));
        $results = $this->_twitter_request($url);
        return $results;
    }

    /**
     * Twitter投稿
     **/
    private function post_twitter()
    {
        if ($_POST['message']) {
            $this->_twitter_auth();
            $message = rawurlencode($_POST['message']);
            $url = "http://twitter.com/statuses/update.json";
            $posts = "status={$message}";
            $results = $this->_twitter_request($url, $posts);
            return $results;
        }
    }

    /**
     * mixiボイス取得
     **/
    private function mixi_voices()
    {
        $this->_mixi_login();
        $url = 'http://mixi.jp/list_echo.pl';
        $headers[] = "Cookie: {$this->cookie}";

        $html = $this->_mixi_request($url, $headers, 'POST');
        $results = $this->_parse_mixi_voice($html);
        return json_encode($results);
    }

    /**
     * mixiボイス投稿
     **/
    private function post_mixi_voice()
    {
        $this->_mixi_login();
        $url = 'http://mixi.jp/list_echo.pl';
        $headers[] = "Cookie: {$this->cookie}";
        $html = $this->_mixi_request($url, $headers, 'GET');
        $post_key = $this->_get_mixi_voice_post_key($html);

        $url = 'http://mixi.jp/add_echo.pl';
        $body = 'てすとー'.date('Y/m/d H:i');
        $posts = array(
            'body' => $body,
            'post_key' => $post_key,
            'redirect' => 'recent_echo',
            'default_value' => $body,
        );
        $html = $this->_mixi_request($url, $headers, 'POST', $posts);
        $results = mb_convert_encoding($html, 'UTF-8', 'EUC-JP');
        echo($results);
    }

    /**
     * データ形式の統一
     **/
    private function _marge_voices($values)
    {
        if (is_array($values)) {
            foreach ($values as $type => $value) {
                $voices = json_decode($value);
        foreach ($voices as $key => $voice) {
                    $time = strtotime($voice->created_at);
                    $sort_times['time'] = $time;
                    $result['type'] = $type; 
                    $result['time'] = $time;
                    $result['created_at'] = date('Y-m-d H:i:s', $time);
                    $result['text'] = $voice->text;
                    $results[] = $result;
               }
            }
        }
    if (is_array($result)) {
            array_multisort($sort_times, SORT_DESC, $results);
        json_encode($results);
        return $results;                            }
    }

    /**
     * twitter認証設定
     **/
    private function _twitter_auth()
    {
        $this->twitter_user_name = TWITTER_USER_NAME;
        $this->twitter_email = TWITTER_EMAIL;
        $this->twitter_password = TWITTER_PASS;
    }

    /**
     * mixi認証設定
     **/
    private function _mixi_auth()
    {
        $this->mixi_id = MIXI_ID;
        $this->mixi_email = MIXI_EMAIL;
        $this->mixi_password = MIXI_PASS;
    }

    /**
     * mixiログイン処理
     **/
    private function _mixi_login()
    {
        $this->_mixi_auth();

        $posts = array(
                'email' => $this->mixi_email,
                'password' => $this->mixi_password,
                'next_url' => 'http://mixi.jp/home.pl'
            );
        $headers[] = 'Content-Type: application/x-www-form-urlencoded';
        $url = 'http://mixi.jp/login.pl';
        $this->_mixi_request($url, $headers, 'POST', $posts);
    }

    /**
     * mixiボイスpost_key取得
     **/
    private function _get_mixi_voice_post_key($html)
    {
        if ($html) {
            $html = mb_convert_encoding($html, 'UTF-8', 'EUC-JP');
        }
        $rows = explode("\n", $html);
        if (is_array($rows)) {
            foreach ($rows as $key => $row) {
                $pattern = '|]+>(.*)]+>|U';
                preg_match("{$pattern}", $row, $values);

                preg_match('/post_key=(.+)&/', $row, $params);
                if ($params) {
                    $post_key = $params[1];
                    if ($post_key) {
                        return $post_key;
                    }
                }
            }
        }
    }

    /**
     * mixiボイスパース
     **/
    private function _parse_mixi_voice($html)
    {
        if ($html) {
            $html = mb_convert_encoding($html, 'UTF-8', 'EUC-JP');
        }
        $rows = explode("\n", $html);
        if (is_array($rows)) {
            foreach ($rows as $key => $row) {
                $pattern = '|]+>(.*)]+>|U';
                preg_match("{$pattern}", $row, $values);

                $pattern_posttime = '';
                if (preg_match("{$pattern_posttime}", $values[0])) {
                    $voice['created_at'] = $values[1];
                    $voice['type'] = 'mixi';
                }

                $pattern_body = '';
                if (preg_match("{$pattern_body}", $values[0])) {
                    $voice['text'] = $values[1];
                    $voices[] = $voice;
                    $voice = null;
                    $values = null;
                }
            }
        }
        return $voices;
    }

    /**
     * mixi共通リクエスト
     **/
    private function _mixi_request($url, $headers, $method, $posts=null) {
        if (is_array($posts)) {
            $content = http_build_query($posts, '', '&');
            $content_length = strlen($content);
            $headers[] = "Content-Length: {$content_length}";

            $params['http']['content'] = $content;
        }

        $params['http']['method'] = $method;
        $params['http']['header'] = implode("\r\n", $headers);

        $context = stream_context_create($params);
        $contents = file_get_contents($url, false, $context);

        //cookie設定
        $this->_set_cokkie_for_response_header($http_response_header);
        return $contents;
    }

    private function _set_cokkie_for_response_header($http_response_header) {
        if (is_array($http_response_header)) {
            foreach ($http_response_header as $r) {
                if (strpos($r, 'Set-Cookie') === false) {
                    continue;
                }
                $params = explode(' ', $r);
                $this->cookies[] = str_replace(';', '', $params[1]);
            }
        if (is_array($this->cookies)) {
               $this->cookie = implode('; ', $this->cookies);
            }
        }
    }

    /**
     * twitter共通リクエスト
     **/
    private function _twitter_request($url, $posts=null)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 2);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        if ($posts) {
            curl_setopt($ch, CURLOPT_POST, 1);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $posts);
        }
        curl_setopt($ch, CURLOPT_USERPWD, "{$this->twitter_email}:{$this->twitter_password}");
        $results = curl_exec($ch);
        curl_close($ch);
        return $results;
    }

    // WSSE Authentication
    function _mixi_wsse_authentication_header() {
        $nonce       = pack('H*', sha1(md5(time().rand().posix_getpid())));
        $created     = date('Y-m-d\TH:i:s\Z');
        $digest      = base64_encode(pack('H*', sha1($nonce . $created . $this->mixi_password)));
        $wsse_format   = 'UsernameToken Username="%s", PasswordDigest="%s", Nonce="%s", Created="%s"';
        $wsse = sprintf($wsse_format, $this->mixi_email, $digest, base64_encode($nonce), $created);
        $header = "X-WSSE: {$wsse}";

        return $header;
    }       
}

  2010/02/05

自宅←→会社の作業での個人プロジェクト共有のお話

ファイル転送ソフトとかいい加減馬鹿らしいので、SVNをyoo-s.comに構築している。 と記事にするまでもないネタだったのだが・・・

http経由でソースをオール公開していたのだが、 個人設定情報も去年から丸見えだった!事に今日気づくw

mixiとtwitterはおろか、Googleアカウントまで乗っ取られるとこだった((_))

取り合えずBasic認証をかける。 やっぱライブラリ系以外のソース公開は無理だな。

■Apache設定

 #vi /etc/apache2/mods-available/dav_svn.conf

  DAV svn
  SVNParentPath /var/svn
  AuthType Basic
  AuthName "Subversion Repository"
  AuthUserFile /etc/apache2/dav_svn.passwd
  AuthzSVNAccessFile /etc/apache2/dav_svn.authz
  
    Require valid-user
  

■Basic認証設定 - ユーザファイル

 #vi /etc/apache2dav_svn.authz

* = r ユーザ名 = rw

  • htpassword
 #htpasswd -c dav_svn.passwd ユーザ名
<< Top < Prev Next > Last >>
php-markdown で バニラPHPなコードブロック処理
laravel-ffmpeg を使う
2021年版 Ubuntu + certbot + Let's Encrypt でサーバ証明書設定
GihHub のデフォルトでない master ブランチを checkout する
マルチログインで未認証のリダイレクト
Homebrew で Redis をインストール
CSS だけでスムーズスクロール
EC-CUBE4 で Gmail の smtp を利用する
Amazon Linux 2 の amazon-linux-extras とは
UNIQUE カラムのバリデーションで自分自身を除外して更新
フォーム有効期限切れで Page Expired をリダイレクト
ログを日付でローテーションやクリアや削除
Homebrew で PHP8.0 から PHP7.4 にダウングレード
Big sur で zsh 移行と Homebrew アップグレード
Mac に minikube をインストール
途中から .gitignore に追加する
Larevel 6.x から Laravel 8.x にバージョンアップ
Composer で Allowed memory size (メモリ不足)エラー
Blade でカスタムクラスを利用する
git push git pull にブランチ指定せずに実行する
git pull や git push できなくなったとき
Docker のコンテナからホストOS に接続
Mac で ローカル IP アドレス(ipv4)のみを表示する
ホストOS から Docker の MySQLコンテナに接続
caching_sha2_password のエラー
node-config で環境設定ファイルを利用する
rootパスワードを初期化(再設定)する
Git から clone したときのエラー対処
Mac に MySQL をインストール
Mac に PostgreSQL をインストール
Laravel 環境構築 - Mac ネイティブ編
Firebase 入門 - Firebase とは
Firebase 入門 - CLI インストールとデータベースの設定
AWS 無料枠(t2.micro)で容量とメモリエラー
Cloud9 を起動する -初心者編-
gcloud で GCEインスタンスを起動してみる
AWS CLI と jq でインスタンス一覧を整形して表示
React と Laravel7 のプロジェクトを作成する
Homebrewインストール-2020年版
3直線で囲まれた範囲塗りつぶし
PuLP で線形最適化問題を解く
カスタムのペジネーションを作る
node-sass を使って sass をコンパイルする
Log ファサードでSQLログを分離して書き出す
いちから始める Docker - 複数のコンテナを使う - (2020年)
いちから始める Docker - docker-compose を使う - (2020年)
AWS ECR を使ってみる
Laravel7 でマルチ認証
Mac に AWS Client を設定する
Laravel7 リリース