2016年6月3日金曜日

letsencryptのerror: ImportError: No module named interface

letsencryptを導入後しばらくほっといたらエラー発生してた。
http://blog.fspm.jp/2016/03/ec2amazon-linuxletsencryptsslhttpsnginx.html

エラー内容は
Automated renewal failed:
Creating virtual environment...
Installing Python packages...
Installation succeeded.
Traceback (most recent call last):
  File "/root/.local/share/letsencrypt/bin/letsencrypt", line 7, in 
    from certbot.main import main
  File "/root/.local/share/letsencrypt/local/lib/python2.7/dist-packages/certbot/main.py", line 11, in 
    import zope.component
  File "/root/.local/share/letsencrypt/local/lib/python2.7/dist-packages/zope/component/__init__.py", line 16, in 
    from zope.interface import Interface
ImportError: No module named interface


この2ヶ月程の間にlib名がletsencrypt -> certbotへ変わったりしてる。

原因はこれ。
https://github.com/certbot/certbot/issues/2823

解決策は
# unset PYTHON_INSTALL_LAYOUT


pipのupgradeとか、python2.6, 2.7とかなんも関係なかった、、、

2016年3月17日木曜日

Chatworkのメッセージ記法リスト(2016.3.16時点)

チャットワークのメッセージ記法は、HTMLタグの< >のように[ ]とブラケット(角括弧)文字にてタグ表記され、 単独のタグとして[tagname:value]や[tagname attr=value]と表記される場合と、[tagname]...[/tagname]のように開始タグと終了タグとで囲む表記があります。
http://developer.chatwork.com/ja/messagenotation.html


使いそう


tag desc
[hr] 罫線(横のライン)
[info][title]見出し[/title]内容[/info] タスク追加や概要編集した際の様なinfo boxが投稿される
[code]...[/code] メッセージ記法を無視して入力したテキストがそのまま表示される+code highlighting


使わなそうだけど有効ぽいもの


tag desc
[preview id=****** ht=150] アップロードした画像を表示。idは数値、htはheight?不明
[To:{account_id}] 宛先
[rp aid={account_id} to={room_id}-{message_id}] 返信
[qt aid={account_id} time={timestamp}]...[/qt] 引用。[引用 aid=228520]...[/引用]の様にqtを引用に置き換えたり、timeを省略してもおk
[picon:{account_id}] アカウントアイコン
[piconname:{account_id}] アイコン+名前



ユーザIDに適当な値を入れるとそのユーザのアイコンや名前が表示される(存在すれば)。これはそういう仕様なのかな。

参考

2016年3月5日土曜日

EC2(Amazon Linux)をletsencryptでSSL(https)証明書設定(nginx利用)


Install letsencrypt - インストール


めんどくさいのでrootで。

# git clone https://github.com/letsencrypt/letsencrypt /usr/local
# cd letsencrypt
# ./letsencrypt-auto --help



Edit nginx conf (for letsencrypt) - letsencryptからの確認アクセス用設定


# vi /etc/nginx/conf.d/virtual.conf (or site-availables ... etc)

---
server {
    listen 80;
    server_name example.jp;

    location '/.well-known/' {
        default_type "text/plain";
        root /tmp/letsencrypttmp;
    }
    location / {
        return 301 https://$host$request_uri;
    }
}



Get certificates - 証明書取得


# mkdir /tmp/letsencrypttmp
# /path/to/letsencrypt-auto certonly --webroot -w /tmp/letsencrypttmp -d example.com --agree-tos

Error が出た。
Downloading zope.interface==4.1.3 (141K)...
Downloading mock==1.0.1 (818K)...
Downloading acme==0.4.2 (95K)...
Downloading letsencrypt==0.4.2 (199K)...
Downloading letsencrypt-apache==0.4.2 (99K)...
You are using pip version 6.0.8, however version 8.0.3 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
Processing /tmp/peep-xGHlQg/argparse-1.4.0-py2.py3-none-any.whl
Installing collected packages: argparse

Successfully installed argparse-1.4.0
You are using pip version 6.0.8, however version 8.0.3 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
Processing /tmp/peep-uCy7pg/pycparser-2.14.tar.gz
Installing collected packages: pycparser
  Running setup.py install for pycparser
    Build the lexing/parsing tables
Successfully installed pycparser-2.14
You are using pip version 6.0.8, however version 8.0.3 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
Processing /tmp/peep-ee_aNB/cffi-1.4.2.tar.gz
Installing collected packages: cffi
  Running setup.py install for cffi
    building '_cffi_backend' extension
    gcc -pthread -fno-strict-aliasing -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic -D_GNU_SOURCE -fPIC -fwrapv -DNDEBUG -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic -D_GNU_SOURCE -fPIC -fwrapv -fPIC -DUSE__THREAD -I/usr/include/python2.7 -c c/_cffi_backend.c -o build/temp.linux-x86_64-2.7/c/_cffi_backend.o
    c/_cffi_backend.c:2:20: fatal error: Python.h: No such file or directory
     #include 
                        ^
    compilation terminated.
    error: command 'gcc' failed with exit status 1

python2.7用のライブラリが欠けてるらしい。
https://community.letsencrypt.org/t/redhat-centos-6-x-users-need-python-2-7/2190

# yum install python27-devel python27-pip python27-setuptools python27-virtualenv

今回はpython27-virtualenvが欠けているだけだった。

最初のコマンドを再実行。以下の結果が出ればOK。/etc/letsencrypt配下にそれぞれファイルが保存される。

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at
   /etc/letsencrypt/live/example.jp/fullchain.pem. Your cert
   will expire on 2016-06-02. To obtain a new version of the
   certificate in the future, simply run Let's Encrypt again.
 - If you like Let's Encrypt, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le


cert.pem(証明書)
chain.pem(中間証明書)
fullchain.pem(cert.pem + chain.pem)
privkey.pem(秘密鍵)




Setting nginx SSL - nginxでSSL設定



# vi /etc/nginx/conf.d/virtual.conf (or site-availables ... etc)

---
server {
    listen 443 ssl;
    ssl on;
    ssl_certificate      /etc/letsencrypt/live/example.jp/fullchain.pem;
    ssl_certificate_key  /etc/letsencrypt/live/example.jp/privkey.pem;
    server_name example.jp;

#    ~~~(略)
}

reloadでSSLが動く
# /etc/init.d/nginx reload



Set auto update script - 自動更新


/path/to/update.sh
#!/bin/sh
if ! /usr/local/letsencrypt/letsencrypt-auto renew --force-renew > /var/log/letsencrypt/renew.log 2>&1 ; then
    echo Automated renewal failed:
    cat /var/log/letsencrypt/renew.log
    exit 1
fi
/etc/init.d/nginx reload

crontabとかに登録。毎月2日4:30。どのくらいのペースで実行すればいいんだろう。
# crontab -e
30 04 02 * * /home/xxxx/letsencrypt/update.sh


セットアップのためになんどもrenewしてたら多すぎって怒られた。5回目くらいからかな。



参考

2015年1月26日月曜日

cake3.0.0-beta から cake3.0.0-RCへのmigration

beta2ぐらいからRCで結構細かく変わってきている。


config/bootstrap.php

load()で.phpをつけてはいけなくなった。
- Configure::load('app.php', 'default', false);
+ Configure::load('app', 'default', false);


config/routes.php

RoutingのCase insensitiveの設定方法が変わった。
+ Router::defaultRouteClass('InflectedRoute');
// Router::extensions(['html', 'json', 'txt']); <-- あとこれはRCで追加されたわけではないけどbeta3位で追加しないと動かなかった。

config/app.php

'path'でpathを指定する必要が出てきた。
 'debug' => [
  'className' => 'Cake\Log\Engine\FileLog',
+  'path' => LOGS,
  'file' => 'debug',
  'levels' => ['notice', 'info', 'debug'],
 ],

src/Model/Table/*Table.php

メソッド名が変わった。古いvalidatePresenceは使用不能に。
-   ->validatePresence('name', 'create')
+   ->requirePresence('name', 'create')

validationタイミングの変更?

validation指定のタイミングの変更。
// old
$entity = $table->newEntity([/* some entity data array */]);
$table->save($entity, ['validate' => false]);

// new
$entity = $table->newEntity([/* some entity data array */], ['validate' => false]);
$table->save($entity);
これはRCからなのか詳しく見てないけど'validate' => 'someMyValidation'みたいな指定が出来るようになったっぽい。


他にもbakeがplugin化してたりなんか色々あるぽいけど、RCから使い出すならその辺は気にせず使える。
ライブラリ自体の修正でなくてskeletonで作成したPHPテンプレに互換性が無くなると対応めんどい。
Zend Frameworkのノリでbetaからstableまでそんな変わらんだろと思ってたけどちょこちょこ変わる。

3.0.0もRCなのでもう変わることはないかな〜。今くらいから使いはじめるのがベストではないかと思われる。

2014年12月16日火曜日

Xcode6でOrganizerからValidate ArchiveするとiTunes Store operation failed. The network connection was lost.になって進まない。

Provisioning Profileを変えても駄目で、Xcode5の事例で出てたrestartも駄目で開発機再起動も駄目で何度やっても弾かれるしどうしようもなくなってたが、Application loaderを使うことで解決。
https://developer.apple.com/library/ios/documentation/LanguagesUtilities/Conceptual/iTunesConnect_Guide_Jpn/Chapters/SubmittingTheApp.html#//apple_ref/doc/uid/TP40014483-CH33-SW8

Organizerでipaにexportして(Save for iOS App Store Deployment)、Application Loaderからアップロードするとそのままアップロード出来た。


というか、新生TestFlightはなぜあんな処理に時間かかるのか。アップロード完了してからアクティブになるまでひどい時だと30分くらいかかる。

2014年12月4日木曜日

単一Fragmentを表示するActivityの共通化

全画面想定のFragmentをActivityで取り回したい場合。AaaFragment, BbbFragmentに合わせてAaaActivity, BbbActivityとか作るのは面倒なのでActivityのWrapperを共通化。

Fragmentは public static XxxFragment newInstance(Bundle args);を実装している想定。
画面遷移時は、FragmentからならWrapperActivity.openFragmentActivity(getActivity(), SecondFragment.class, secondFragmentsArguments); という感じで行える。

package hoge.fuga.activities;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.View;
import android.view.View.OnClickListener;
import jp.arithmetic.arithmusic.R;
import jp.arithmetic.arithmusic.model.FragmentReplacer;

public class WrapperActivity extends Activity {
 public static final String TAG = "WrapperActivity";
 public static final String ARGS_FRAGMENT = "app-fragment";
 
 
 /** 
  * 1つのFragmentを全面に表示する共通化Activity
  * @param fromActivity
  * @param clazz
  * @param args
  */
 public static void openFragmentActivity(Activity fromActivity, Class clazz, Bundle args) {
  // setup bundle
  if (args == null) {
   args = new Bundle();
  }
  args.putString(ARGS_FRAGMENT, clazz.getName());
  
  // setup intent
  Intent i = new Intent(fromActivity, WrapperActivity.class);
  i.putExtras(args);
  
  // start activity
  fromActivity.startActivity(i);
 }
 
 /** 
  * close
  * @param fromActivity
  */
 public static void closeFragmentActivity(Activity fromActivity) {
  fromActivity.finish();
 }
 
 public static void closeToStartActivity(Activity fromActivity) {
  Intent i = new Intent(fromActivity, SomeStartActivity.class);
  i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
  i.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
  fromActivity.startActivity(i);
 }
 
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_empty_container);

  // intentパラメータ優先
  Bundle args = (getIntent() != null) ? getIntent().getExtras() : savedInstanceState;
  if (args == null) {
   throw new RuntimeException("Wrapper: Empty arguments");
  }
  
  // 呼び出しFragment特定、初期化
  String className = args.getString(ARGS_FRAGMENT);
  if (className == null || className.isEmpty()) {
   throw new RuntimeException("Wrapper: Empty class name");
  }
  Fragment f = null;
  try {
   Class clazz = Class.forName(className);
   Method newInstance = clazz.getMethod("newInstance", Bundle.class);
   f = (Fragment)newInstance.invoke(null, args);

   replaceFragment(f);
   
  } catch (ClassNotFoundException e) {
   e.printStackTrace();
   finish();
  } catch (NoSuchMethodException e) {
   e.printStackTrace();
   finish();
  } catch (IllegalAccessException e) {
   e.printStackTrace();
   finish();
  } catch (IllegalArgumentException e) {
   e.printStackTrace();
   finish();
  } catch (InvocationTargetException e) {
   e.printStackTrace();
   finish();
  }
 }
 
 @Override
 public void onBackPressed() {
  if (getSupportFragmentManager().getBackStackEntryCount() == 1) {
   closeFragmentActivity(this);
  } else {
   super.onBackPressed();
  }
 }
 
 
 public void replaceFragment(Fragment f) {
  getSupportFragmentManager()
  .beginTransaction()
  .addToBackStack(null)
  .replace(R.id.empty_container, f)
  .commit();
 }
}

2014年11月17日月曜日

AndroidでBlur effect

要はiOS7以降のBlur effectぽいことをしたい場合。
android-stackblurを使う。
・RenderScriptはradiusがMAX25までしか設定できないぽいので期待しない。
・Eclipse想定


StackBlurライブラリの開発プロジェクトへのインストール

NDK導入
・stackblurをDLして、StackBlurディレクトリをプロジェクトimport。
・プロジェクトのコンテキストメニューから、Build Project
・libsディレクトリ配下にビルド成果物ができるので、まるっと開発プロジェクトのlibs配下にコピー
※stackblurのrenderscript8.jarでの競合が無ければIs Libraryでの追加でも大丈夫かも。


利用例

StackBlurManager _stackBlurManager = new StackBlurManager(orig);
_stackBlurManager.processNatively(radius);
Bitmap blurred = _stackBlurManager.returnBlurredImage();

利用例:Dialogで使う場合

Dialogに背景画像設定する場合は、DialogのWindow層に設定。
>そうするとDialogの位置とサイズが崩れる。styleで色々設定しても駄目。
>なのでAlertDialogは諦めて自前でCustomViewを作る必要がある。
>それも含めたベースのDialogFragment

/hoge/fuga/AbstractDialogFragment.java
package hoge.fuga;

import com.enrique.stackblur.StackBlurManager;

import hoge.fuga.R;

import android.annotation.SuppressLint;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnShowListener;
import android.graphics.Bitmap;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.FrameLayout;

abstract public class AbstractDialogFragment extends DialogFragment implements OnShowListener {

    public static final String TAG = "AbstractDialogFragment";

    protected Dialog mDialog;
    private ViewGroup mContainer;


    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        mDialog = super.onCreateDialog(savedInstanceState);

        // Get status bar height
        Rect rectgle= new Rect();
        getActivity().getWindow().getDecorView().getWindowVisibleDisplayFrame(rectgle);
        int statusBarHeight = rectgle.top;

        // Screen shot http://stackoverflow.com/a/9596132/1121509
        View v = getActivity().getWindow().getDecorView();
        v.setDrawingCacheEnabled(true);
        Bitmap ss = v.getDrawingCache();
        if (ss != null) {
            ss = Bitmap.createBitmap(ss, 0, statusBarHeight, ss.getWidth(), ss.getHeight() - statusBarHeight);
        }
        v.setDrawingCacheEnabled(false);

        // Blur effect
        if (ss != null) {
            int radius = (int) (ss.getHeight() * 0.25);
            radius = radius > 100 ? 100 : radius;
            
            StackBlurManager _stackBlurManager = new StackBlurManager(ss);
            _stackBlurManager.processNatively(radius);
            Bitmap blurred = _stackBlurManager.returnBlurredImage();
            mDialog.getWindow().setBackgroundDrawable(new BitmapDrawable(getResources(), blurred));
        }

        // without title
        mDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);

        // set listener
        mDialog.setOnShowListener(this);

        return mDialog;
    }
    
    
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        // コンテナの設定
        mContainer = (ViewGroup) inflater.inflate(R.layout.dialog_base, container, false);
        return mContainer;
    }

    public void addViewToContainer(View contentView) {
        ((ViewGroup) mContainer.findViewById(R.id.dialog_container)).addView(contentView, 0);
    }

    @SuppressLint("NewApi")
    @SuppressWarnings("deprecation")
    @Override
    public void onShow(DialogInterface dialog) {
        // サイズ調整、このタイミングでないとうまく動かない
        Point size = new Point();
        Display display = getActivity().getWindowManager().getDefaultDisplay();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
            display.getSize(size);
        } else {
            size.x = display.getWidth();
            size.y = display.getHeight();
        }

        FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams)mContainer.getLayoutParams();
        lp.width = size.x;
        lp.height = size.y;

        ViewGroup dialogContainer = (ViewGroup) mContainer.findViewById(R.id.dialog_container);
        FrameLayout.LayoutParams lp2 = (FrameLayout.LayoutParams) dialogContainer.getLayoutParams();
        lp2.topMargin = (size.y - dialogContainer.getMeasuredHeight()) / 2;
    }
}

/res/layout/dialog_base.xml



    
        
    


・Dialogを使う場合はAbstractDialogFragmentをextend。
・dialogの設定をするときはonCreateDialog()をoverrideしてsuper.onCreateDialog()してから設定。
・ViewはonCreateView()をoverrideして、super.onCreateView()してから子Viewを作り、super.addViewToContainer(childDialogView)する。


GPUImage for androidがblur effect対応してくれたら嬉しいな〜。