2012年8月10日金曜日

Google APIs Calnedar & OAuth2.0 (v3/v2)

はじめに

Google APIs を使うコマンドラインを書いてみました。自分のイベントとか見たい方は適当に改良してください。:-)

** かぶりネタですが興味のある方は読んでください。**


Usage

USAGE
      gapicalendarlist.sh  v2|v3

RESET SETTINGS
      remove 'v2.gapi.token' or 'v3.gapi.token'

DEPENDENCIES
      lynx, curl


解説のようなメモのような

簡単に認証と処理内容を書いてみました

認証の種類

Version 2 : using ClientLogin
  • OAuth
  • AuthSub
  • ClientLogin
Version 3 : using OAuth -> Devices

知識の足りなさ等の諸事情で Devices の方法を選択してます。

Installed Applicatoins の方式で、https://accounts.google.com/o/oauth2/auth にリクエストするとHTMLコンテンツがかえって来ます。これはシェルであれこれするのが面倒だったのでやめました。
Devices方式で、https://accounts.google.com/o/oauth2/device/code にリクエストをすると、JSONがかえってpiar毎に改行されているのでシェルで扱いやすいのでこちらを選択しました

  • OAuth
    • Login
    • Web Server Applications
    • Client-size Applications
    • Installled Applications (Winwdows, iOS, Android, Blackberry)
    • Devices
    • Service Accounts

処理内容

*** Google のサイトを見た方がいいと思ったので割愛します。 ***

 [ shell ]                  [ google ]
    |                            |
    |                            |
    +----- get user token -----> +  URL 1 
    |                            |
    | <------ user token --------+
    |     and other params       |
    |          JSON              |
    |                            |
    +----+                       |
    |    | save token            |
    |<---+                       |
    |         [ lynx ]           |
    |            |               |
    +-- verify ->|               |
    |    URL     +-- Sign in --> |
    |            |               |
    |            |<- user code --+
    |            |     form      |
    |            |               |
    |            +- user code -->|
    |            |               |
    |            |<- allow acces-+
    |            |  confirm page |
    |            |               |
    |            +-allow submit->|
    |            |               |
    |            |<- result page-+
    |            |               |
    |                            |
    |                            |
    |                            |
    |                            |
    +------ get access token --->+ URL 2 
    |                            |
    | <------ access token ------+
    |       and other params     |
    |           JSON             |
    |                            |
    +----+                       |
    |    | save token            |
    |<---+                       |
    |                            |
    |                            |
    +----- get calendar list --->+  URL 3
    |                            |
    | <----- calendar list ------+
    |         JSON               |
    |                            |
    |                            |


URL 1 https://accounts.google.com/o/oauth2/device/code
URL 2 https://accounts.google.com/o/oauth2/token
URL 3 https://www.googleapis.com/calendar/v3/users/me/calendarList

Reference Link

Google OAuth 2.0

Google APIs Calendar



Source & Screen cast

#!/bin/bash
# ------------ parameters ------------
api_version=$1
# if need set, please remove these files.
token_file="v2.gapi.token"
user_code_file="v3.gapi.token"
# *************************************
# account : need setting
# *************************************
# ClientLogin
username=yourmail@address.net
password=xxxx
# oauth 2.0
client_id=your.account.clientId
client_secret=
# ------------ functions ------------
#
# Version 2
#
function V2ClientLoginAndCalendarList {
# [company-id]-[app-name]-[app-version]
applicationName="mycompany-googleapi.sh-v1"
# cl (Calendar) / mail (Gmail) / blogger (Blogger)
serviceName="cl"
# GOOGLE / HOSTED / HOSTED_OR_GOOGLE
accountType="HOSTED_OR_GOOGLE"
#
# login , get token
#
if [ -e ${token_file} ]; then
TOKEN=`cat ${token_file}`
else
URL="https://www.google.com/accounts/ClientLogin"
parameters="Email=${username}&Passwd=${password}&source=${applicationName}&service=${serviceName}&accountType=${accountType}"
TOKEN=`curl -s -d "${parameters}" -k ${URL} -H "GData-Version: 2" | awk '{if (/Auth/) {print $0;}}' | sed 's/=/ /' | awk '{print $2}'`
echo ${TOKEN} > ${token_file}
# for interval
sleep 5
fi
# get calendar list
URL="https://www.google.com/calendar/feeds/default/owncalendars/full"
curl -s -H "GData-Version: 2" -H "Authorization: GoogleLogin auth=${TOKEN}" -k ${URL}
}
#
# Version 3
#
function V3OAuthAndCalendarList {
# for lynx
#LANG=en
#export LANG
scope="https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/calendar https://www.googleapis.com/auth/calendar.readonly"
#scope="https://www.googleapis.com/auth/calendar https://www.googleapis.com/auth/calendar.readonly"
#
# obtain user code
#
if [ ! -e ${user_code_file} ]; then
URL="https://accounts.google.com/o/oauth2/device/code"
parameters="scope=${scope}&client_id=${client_id}"
curl -s -k ${URL} -d "${parameters}" | sed 's/"/ /g' | awk '{ if (NF > 3) {printf("%s=%s\n", $1, $3);}}' > ${user_code_file}
fi
source ${user_code_file}
#
# allow api using and obtain access token
#
if [ "${access_token}" = "" ]; then
echo "********* COPY ************"
echo "user_code: ${user_code}"
echo "********* COPY ************"
sleep 8
lynx "${verification_url}"
URL="https://accounts.google.com/o/oauth2/token"
parameters="client_id=${client_id}&client_secret=${client_secret}&code=${device_code}&grant_type=http://oauth.net/grant_type/device/1.0"
curl -s -H "GData-Version: 3" -k ${URL} -d "${parameters}" | sed 's/"/ /g' | awk '{ if (NF > 3) {printf("%s=%s\n", $1, $3);}}' >> ${user_code_file}
source ${user_code_file}
fi
#
# get calendar
#
URL=https://www.googleapis.com/calendar/v3/users/me/calendarList
curl -s -k ${URL} -H "Authorization: Bearer ${access_token}"
}
function UsageMessage {
echo "USAGE"
echo " gapicalendarlist.sh v2|v3"
echo ""
echo "RESET SETTINGS"
echo " remove '${token_file}' or '${user_code_file}'"
echo ""
echo "DEPENDENCIES"
echo " lynx, curl"
echo ""
}
# ------------ logic ------------
if [ "${client_id}" = "your.account.clientId" -o "${username}" = "yourmail@address.net" ]; then
echo "**********************************"
echo "PLEASE SETUP ACCOUNT PARAMETERS"
echo "**********************************"
echo ""
echo "v2 => uesername , password"
echo "v3 => client_id , client_secret"
echo ""
echo "**********************************"
UsageMessage
elif [ "${api_version}" = "v3" ]; then
V3OAuthAndCalendarList
elif [ "${api_version}" = "v2" ]; then
V2ClientLoginAndCalendarList
else
UsageMessage
fi

ttyplay


2012年4月25日水曜日

web server benchmark : apache lighttpd nodejs warp yesod tomcat jetty

結論

QCon 2012 で Warp+Yesod がいいと言っていたので、ベンチをとってみました。いいっぽいです

サーバーサイドのチューニングはデフォなので、スレッド数位は合わせてベンチマークをとりたいと思って下ります。 なんかサーセン

環境

Server

Ubuntu 11.10

Intel(R) Xeon(R) CPU 5160 @ 3.00GHz x 2

Memory 2 GiB

|

Switching Hub

corega Fast SW-8D

|

Client

Mac OS X 10.7.3

2.53 GHz Intel Core i5

Memory 8 GB 1067 MHz DDR3

計測の仕方

$ ab -n request_count -c 128 -r -g gnuplot_file_name   http://ubuntu.server:port/path   >& result.txt

This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

計測したもの

Apache Lighttpd

Server Software:        Apache/2.2.20
Server Hostname:        xxx.xxx.xxx.xxx
Server Port:            80

Document Path:          /index.html
Document Length:        85 bytes

Server Software:        lighttpd/1.4.30
Server Hostname:        xxx.xxx.xxx.xxx
Server Port:            8123

Document Path:          /index.html
Document Length:        85 bytes

Node.js Warp + Yesod

version: 0.6.15


Server Software:        
Server Hostname:        xxx.xxx.xxx.xxx
Server Port:            8124

Document Path:          /
Document Length:        80 bytes

ghc: 7.0.3

warp: 1.2.0.1

yesod: 1.0.0.2


Server Software:        Warp/1.2.0.1
Server Hostname:        xxx.xxx.x.160
Server Port:            8123

Document Path:          /index
Document Length:        99 bytes
Tomcat Jetty

Server Software:        Apache-Coyote/1.1
Server Hostname:        xxx.xxx.xxx.xxx
Server Port:            8080

Document Path:          /sample/index.html
Document Length:        85 bytes


Server Software:        Jetty(8.1.2.v20120308)
Server Hostname:        xxx.xxx.xxx.xxx
Server Port:            8080

Document Path:          /sample/index.html
Document Length:        85 bytes

計測結果

wait time 分布図

30000 request

10000 request

wait time について => Between writing request and reading response

Source らしい(何となく怪しい) から一部抜粋

struct data {
#ifdef USE_SSL
    /* XXX insert timings for ssl */
#endif
    int read;                   /* number of bytes read */
    long starttime;             /* start time of connection in seconds since
                                 * Jan. 1, 1970 */
    long waittime;              /* Between writing request and reading response */
    long ctime;                 /* time in ms to connect */
    long time;                  /* time in ms for connection */
};

テスト時間 (sec)

apache, lighttpd はリクエスト数が多いとテストに時間がかかります。

result/apache-time.dat
request  1       2       3       4
  200    0.028   0.035   0.030   0.031
  500    0.081   0.087   0.078   0.069
 1500    0.187   0.172   0.187   0.185
10000   90.143 109.438 107.131 104.303
30000   18.995   3.584  32.986 327.660

result/lighttpd-time.dat
request  1       2       3       4
  200    0.025   0.025   0.027   0.026
  500    0.063   0.069   0.055   0.053
 1500    2.139   0.561   0.168   0.169
10000  50.097   52.646   2.285  34.739
30000 142.147    5.152 165.114 162.209

result/nodejs-time.dat
request  1      2        3       4
  200    0.034  0.039    0.034   0.032
  500    0.097  0.074    0.073   0.072
 1500    0.238  0.235    0.245   0.211
10000    1.560  1.610    5.101   1.505
30000    8.593 24.368   16.838  31.659

result/warp-time.dat
request  1      2        3       4
  200    0.071  0.093    0.074   0.070
  500    0.160  0.309    0.229   0.176
 1500    1.264  1.057    1.326   1.048
10000    3.115 10.991   11.347   5.078
30000   33.264 34.866   33.098  34.690

result/tomcat-time.dat
request  1      2        3       4
  200    0.021  0.024    0.025   0.080
  500    0.052  0.050    0.049   0.043
 1500    0.151  0.167    0.166   0.153
10000    9.062 10.112    6.957   0.965
30000   21.004 12.324   21.602  18.784

result/jetty-time.dat
request  1      2        3       4
  200    0.025  0.025    0.026   0.028
  500    0.087  0.104   14.926   0.059
 1500    1.127 22.815    1.244  14.990
10000   11.779 11.658   11.648  11.617
30000   36.141 36.806   36.773  36.225

2012年4月18日水曜日

組込み Tomcat と Jetty : Embedded in java

TomcatとJettyの組込みです バージョンは下記です
  • Tomcat 7.0.26
  • Jetty 8.1.12

Tomcat 参考サイト

embedding-tomcat

コマンド

起動は下の感じで、止めるのは Ctrl-C でお願いします
# tomcat
$ java -cp srv.jar:lib/* web.server.WebServer

# jetty
$ java -cp srv.jar:lib/* web.server.WebServer -jetty

# set port
$ java -cp srv.jar:lib/* web.server.WebServer server.port 8123

他のパラメータはソースを見てください
動かした感じ, jetty の後 tomcat 動かしてます










ソース

//
// Embbed Web Server
//
// Property
// ----------
//
// server.port port number
// server.basedir base dir path.
// server.webapps webapp dir name.
// server.contextpath context path of web app
// server.maxthreads
// server.minthreads
//
//
// server.secure true/false
// server.secure.key.alias alias
// server.secure.key.password keystore pasword
// server.secure.key.file keystore file path
// server.secure.ssl.protocol protocol
//
//
// Dir
// ----------
//
// home.dir/
// server.jar jar file of this class
// lib/ tomcat libs & jetty
// webapps/
// sample/
// WEB-INF/
// lib/webservlet.jar or your servlet.jar
// indx.html
//
//
// @author wooyoowaan@gmail.com
//
package web.server;
import java.io.File;
import java.io.FilenameFilter;
import java.util.Properties;
import java.util.StringTokenizer;
import javax.servlet.ServletException;
// TOMCAT
import org.apache.catalina.LifecycleException;
import org.apache.catalina.startup.Tomcat;
//import org.apache.catalina.connector.Connector;
// JETTY
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.eclipse.jetty.server.ssl.SslSelectChannelConnector;
abstract public class WebServer {
// server configuration
public static final String PROPS_PORT = "server.port";
public static final String PROPS_BASEDIR = "server.basedir";
public static final String PROPS_WEBAPPS = "server.webapps";
public static final String PROPS_CONTEXTPATH = "server.contextpath";
public static final String PROPS_RESOURCE_BASE= "server.resourcebase";
public static final String PROPS_WAR = "server.war";
public static final String PROPS_EXTRA_CLASSPATH = "server.extr.classpath";
public static final String PROPS_MAX_THREADS = "server.maxthreads";
public static final String PROPS_MIN_THREADS = "server.minthreads";
// scurity properties
public static final String PROPS_SECURE = "server.secure";
public static final String PROPS_KEY_ALIAS = "server.secure.key.alias";
public static final String PROPS_KEY_PASSWORD = "server.secure.key.password";
public static final String PROPS_KEY_FILE = "server.secure.key.file";
public static final String PROPS_SSL_PROTOCOL = "server.secure.ssl.protocol";
public static final String PROPS_CLIENT_AUTH = "server.secure.client.auth";
protected Properties _properties;
/**
* start web server
*/
public void start() {
doStart();
}
/**
* stop web server
*/
public void stop() {
doStop();
}
abstract protected void doStart();
abstract protected void doStop();
protected void check(StateChecker checker) throws Exception {
Thread thread = new Thread(checker);
thread.start();
thread.join();
}
/**
*
*/
protected int getInt(String name, int defaultValue) {
String s = _properties.getProperty(name);
return s == null ? defaultValue : Integer.parseInt(s) ;
}
/**
*
*/
protected String getProperty(String name, String defaultValue) {
return _properties.getProperty(name, defaultValue);
}
/**
*
*/
protected boolean getBool(String name, boolean defaultFlag) {
String s = _properties.getProperty(name, null);
return s == null ? defaultFlag : Boolean.parseBoolean(s);
}
public static void main(String[] args) {
Properties props = new Properties();
boolean useTomcat = true;
for (int i = 0; i < args.length ; i++) {
String arg = args[i];
if (arg.equals("-jetty")) {
useTomcat = false;
} else {
String key = arg;
i++;
String value = args[i];
props.setProperty(key, value);
}
}
final WebServer server = useTomcat ? new TomcatServer(props) : new JettyServer(props) ;
try {
server.start();
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
server.stop();
}
});
while (true) {}
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* Jetty Server
*/
class JettyServer extends WebServer {
private Server _server;
/**
*
*/
public JettyServer(Properties props) {
_properties = props;
}
/**
*
*/
protected void doStart() {
_server = new Server();
int maxThreads = getInt(PROPS_MAX_THREADS, 200);
int minThreads = getInt(PROPS_MIN_THREADS, 8);
QueuedThreadPool threadPool = new QueuedThreadPool();
threadPool.setMinThreads(minThreads);
threadPool.setMaxThreads(maxThreads);
this._server.setThreadPool(threadPool);
Connector connector = null;
if (getBool(PROPS_SECURE, false)) {
SslSelectChannelConnector sslConnector = new SslSelectChannelConnector();
sslConnector.setKeystore(getProperty(PROPS_KEY_FILE, "keystore/sha1.keystore"));
sslConnector.setKeyPassword(getProperty(PROPS_KEY_PASSWORD, "password"));
sslConnector.setProtocol(getProperty(PROPS_SSL_PROTOCOL, "TLS"));
//sslConnector.setPassword();
// trust ...
connector = sslConnector;
connector.setPort(getInt(PROPS_PORT, 8443));
} else {
connector = new SelectChannelConnector();
connector.setPort(getInt(PROPS_PORT, 8080));
}
// set connectors
this._server.setConnectors(new Connector[] { connector });
//
// setup
//
WebAppContext ctx = new WebAppContext(getProperty(PROPS_WEBAPPS,"webapps"),
getProperty(PROPS_CONTEXTPATH, "/sample"));
ctx.setExtractWAR(true);
ctx.setResourceBase(getProperty(PROPS_RESOURCE_BASE, "webapps/sample"));
ctx.setWar(getProperty(PROPS_WAR, "/sample"));
String extraClasspath = getProperty(PROPS_EXTRA_CLASSPATH, null);
if (extraClasspath != null) {
ctx.setExtraClasspath(getClassPath(extraClasspath));
}
ctx.setServer(_server);
_server.setHandler(ctx);
//
// start
//
try {
_server.start();
check(new StateChecker() {
public boolean isOK() {
return _server.isRunning() || _server.isFailed();
}
});
} catch (Exception e) {
throw new IllegalStateException("Jetty Boot Failed", e);
}
if (_server.isFailed()) {
throw new IllegalStateException("Jetty Boot Failed");
}
}
/**
*
*/
protected void doStop() {
try {
_server.stop();
if (!_server.isStopped()) {
check(new StateChecker() {
public boolean isOK() {
return _server.isStopped() || _server.isFailed();
}
});
}
} catch (Exception e) {
throw new IllegalStateException("jetty stop failed");
}
if (_server.isFailed()) {
throw new IllegalStateException("jetty stop failed");
}
_server = null;
}
private String getClassPath(String extraPath) {
try {
StringBuilder classPath = new StringBuilder();
StringTokenizer st = new StringTokenizer(extraPath, ",;");
while (st.hasMoreTokens()) {
File dir = new File(st.nextToken());
File[] flst = dir.listFiles(new FilenameFilter() {
public boolean accept(File file, String name) {
return name.endsWith(".jar") || name.endsWith(".zip") || name.endsWith(".class");
}
});
for (File f : flst) {
if (classPath.length() > 0) {
classPath.append(',');
}
classPath.append(f.toURI().toURL());
}
}
return classPath.toString();
} catch (Exception e) {
// ignore
}
return extraPath;
}
}
/**
* Tomcat
*/
class TomcatServer extends WebServer {
private Tomcat _server;
/**
*
*/
public TomcatServer(Properties props) {
_properties = props;
}
/**
*
*/
protected void doStart() {
_server = new Tomcat();
File baseDir = new File(getProperty(PROPS_BASEDIR, "."));
_server.setBaseDir(baseDir.getAbsolutePath());
// https
if (getBool(PROPS_SECURE, false)) {
org.apache.catalina.connector.Connector connector = new org.apache.catalina.connector.Connector("HTTP/1.1");
int port = getInt(PROPS_PORT, 8443);
connector.setPort(port);
connector.setSecure(true);
File keyStoreFile = new File(baseDir, getProperty(PROPS_KEY_FILE, "keystore/sha1.keystore"));
connector.setScheme("https");
connector.setAttribute("keyAlias", getProperty(PROPS_KEY_ALIAS, "tomcat"));
connector.setAttribute("keystoreFile", keyStoreFile.getAbsolutePath());
connector.setAttribute("keystorePass", getProperty(PROPS_KEY_PASSWORD, "password"));
connector.setAttribute("clientAuth", getProperty(PROPS_CLIENT_AUTH, "false"));
connector.setAttribute("sslProtocol", getProperty(PROPS_SSL_PROTOCOL, "TLS"));
connector.setAttribute("SSLEnabled", true);
//_server.setConnector(connector);
_server.getService().addConnector(connector);
/*
Connector defaultConnector = _server.getConnector();
defaultConnector.setRedirectPort(port);
System.out.println("Con [" + );
for (Connector con : _server.getService().findConnectors()) {
System.out.println(con);
if (con != connector) {
con.setRedirectPort(port);
}
}
*/
} else {
_server.setPort(getInt(PROPS_PORT, 8080));
}
File webApps = new File(baseDir, getProperty(PROPS_WEBAPPS, "webapps"));
_server.getHost().setAppBase(webApps.getAbsolutePath());
try {
String contextPath = getProperty(PROPS_CONTEXTPATH, "/sample");
_server.addWebapp(contextPath, new File(webApps, contextPath).getAbsolutePath());
_server.start();
} catch (ServletException e) {
throw new IllegalStateException("tomcat boot failed!!", e);
} catch (LifecycleException e) {
throw new IllegalStateException("tomcat boot failed!!", e);
}
}
/**
*
*/
protected void doStop() {
try {
_server.stop();
} catch (LifecycleException e) {
throw new IllegalStateException("tomcat stop failed!!", e);
}
}
}
class StateChecker implements Runnable {
public boolean isOK() {return true;}
public void run() {
while (!isOK()) {
try {
Thread.currentThread().sleep(1000);
} catch (Exception e) {
break;
}
}
}
}
view raw WebServer.java hosted with ❤ by GitHub

2012年4月11日水曜日

タネマキは使える

週末にフラッとタネマキに行ってきました。

混む時もあるそうですが、おおよそ使えるのでは無いでしょうか?

ここです!!タネマキ

2012年3月27日火曜日

CAEmitterCell のパクリネタ

ネタが無いので、パクリました。_( TxT)_

Emitting (発光 by Google 翻訳先生) のパクリネタ

本家を読んでくださいね。

パクリ元

UIKit Particle System in iOS 5 Tutorial

参考という名目のパクリ元

CAEmitterLayer and CAEmitterCellアップるぅぅぅの記事ですよね

その他ぽいの


プロパティの説明

CAEmitterCell
birthRate毎秒どれくらいオブジェクトを作るか
lifetimeセルのライフタイム
colortint 色合いを設定
contentsCGImageRef を設定


Layer は emitterShape と emitterPosition を設定するくらいでしょうか

CAEmitterLayer
emitterShapeオブジェクトの作成方法を設定

動かすとこんな感じ


使った適当な画像はこれです


ソース

ファイルのコメント的にはコピペはOKそうだったのですが。
問題ありましたらご指摘ください

//
// DSAppDelegate.m
// DrawSmoke
//
// Created by developer on 12/03/27.
// Copyright (c) 2012 your good mind. All rights reserved.
//
#import "DSAppDelegate.h"
#import <QuartzCore/QuartzCore.h>
#if __has_feature(objc_arc)
#define ARC_ON
#define AUTORELEASE(A) A
#define RETAIN(A) A
#define RELEASE(A)
#else
#define ARC_OFF
#define AUTORELEASE(A) [A autorelease]
#define RETAIN(A) [A retain]
#define RELEASE(A) [A release]
#endif
//
// SmokeView
//
@interface DSSmokeView : UIView
@end
@implementation DSSmokeView
-(id) initWithFrame:(CGRect)frame {
if ((self = [super initWithFrame:frame]) != nil) {
CAEmitterLayer* fireEmitter = (CAEmitterLayer*)self.layer;
fireEmitter.emitterPosition = CGPointMake(self.bounds.size.width/2, self.bounds.size.height);
fireEmitter.emitterMode = kCAEmitterLayerSurface; //kCAEmitterLayerOutline;
fireEmitter.emitterShape = kCAEmitterLayerLine; // kCAEmitterLayerSphere; kCAEmitterLayerCircle; kCAEmitterLayerPoint;
fireEmitter.emitterSize = CGSizeMake(self.bounds.size.width/5,self.bounds.size.width/5 );
float gas=.6;
CAEmitterCell *smoke = [CAEmitterCell emitterCell];
smoke.BirthRate = 0;//11;
smoke.emissionLongitude = -M_PI ;
smoke.emissionLatitude = -M_PI;
smoke.lifetime = gas*4;
smoke.Velocity = 40;
smoke.VelocityRange = 20;
smoke.emissionRange = M_PI / 4;
smoke.Spin = 1;
smoke.SpinRange = 6;
smoke.yAcceleration = -160;
smoke.Scale = 0.3f;
smoke.AlphaSpeed = -0.22f;
smoke.ScaleSpeed = 0.7f;
smoke.color = [[UIColor colorWithRed:1 green:1 blue:1 alpha:0.3*gas] CGColor];
smoke.contents = (id)[[UIImage imageNamed:@"smoke.png"] CGImage];
[smoke setName:@"smoke"];
fireEmitter.emitterCells = [NSArray arrayWithObject:smoke];
}
return self;
}
+ (Class) layerClass {
//configure the UIView to have emitter layer
return [CAEmitterLayer class];
}
-(void)setEmitterPositionFromTouch: (UITouch*)t {
CAEmitterLayer* smokeEmitter = (CAEmitterLayer*)self.layer;
//change the emitter's position
smokeEmitter.emitterPosition = [t locationInView:self];
}
-(void)setIsEmitting:(BOOL)isEmitting {
CAEmitterLayer* smokeEmitter = (CAEmitterLayer*)self.layer;
//turn on/off the emitting of particles
[smokeEmitter setValue:[NSNumber numberWithInt:isEmitting?50:0] forKeyPath:@"emitterCells.smoke.birthRate"];
}
@end
//
// ViewController
//
@interface DSViewController : UIViewController
@end
@implementation DSViewController
-(void) loadView {
CGRect screen = [[UIScreen mainScreen] bounds];
DSSmokeView* smoke = [[DSSmokeView alloc] initWithFrame:screen];
smoke.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
smoke.backgroundColor = [UIColor whiteColor];
self.view = smoke;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
[(DSSmokeView*)self.view setEmitterPositionFromTouch: [touches anyObject]];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[(DSSmokeView*)self.view setEmitterPositionFromTouch: [touches anyObject]];
[(DSSmokeView*)self.view setIsEmitting:YES];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[(DSSmokeView*)self.view setIsEmitting:NO];
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
[(DSSmokeView*)self.view setIsEmitting:NO];
}
@end
//
// DSAppDelegate
//
//
// Header File
// #import <UIKit/UIKit.h>
//
// @interface DSAppDelegate : UIResponder <UIApplicationDelegate>
//
// @property (strong, nonatomic) UIWindow *window;
//
// @end
//
//
//
//
@implementation DSAppDelegate
@synthesize window = _window;
#ifdef ARC_OFF
- (void)dealloc {
[_window release];
[super dealloc];
}
#endif
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
self.window.rootViewController = AUTORELEASE([[DSViewController alloc] initWithNibName:nil bundle:nil]);
[self.window makeKeyAndVisible];
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application {}
- (void)applicationDidEnterBackground:(UIApplication *)application {}
- (void)applicationWillEnterForeground:(UIApplication *)application {}
- (void)applicationDidBecomeActive:(UIApplication *)application {}
- (void)applicationWillTerminate:(UIApplication *)application {}
@end
view raw DSAppDelegate.m hosted with ❤ by GitHub

2012年1月25日水曜日

続 NSURLConnectionDelegateで証明書(ry..方法

前回の記事が適当すぎたので、少ししっかり調べたーー

参考になると幸いです

結論

SSL周りのリリースノート、仕様書とかきちんとでてますか?

知っている方いたら教えてください

環境

  • iOS 5.0
  • tomcat 7.0.23 / 6.0.32
  • xcode 4.2.1

適当にする方法(改め)

- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
  NSURLProtectionSpace * protectionSpace = [challenge protectionSpace];
  NSURLCredential* credentail = [NSURLCredential credentialForTrust:[protectionSpace serverTrust]];
  [[challenge sender] useCredential:credentail forAuthenticationChallenge:challenge];
}

ハマった事

結論

RSAはOKでDSAはNG

ハマっている世界

iOS 5.0 は 証明書に MD5 を非サポートになったので、

keytool のデフォルト動作だと MD5withRSA なので

自己証明のSSL通信が軒並み エラーになると思っていた

SHA1withRSA とかkeystoreを作り直すと上のコード動いたと勘違いした。

安心したので,MD5の証明書でもやってみたら案の定動作したので、アレ?と思い

DSA で作成したら軒並みエラーなった。

--- 以上 ----

エラーの違い

xcode: Console

SHA1withRAS, MD5withRAS

SHA1withDAS

iPad : Safari : RSA

iPad : Safari : DSA

証明書一部

2012年1月23日月曜日

NSURLConnectionDelegateで証明書周りを適当にする方法

自己証明書だと、通信に失敗するでの軒並みOKにするには下のコードで行ける!!

おすすめはしない!!

※ コマンドラインでしか試してません ※

- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace {
  return YES;
}

- (BOOL)connectionShouldUseCredentialStorage:(NSURLConnection *)connection {
  return YES;
}

- (void) connection:(NSURLConnection *)conn didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
  NSURLProtectionSpace * protectionSpace = [challenge protectionSpace];
  NSURLCredential* credentail = [NSURLCredential credentialForTrust:[protectionSpace serverTrust]];
  [[challenge sender] useCredential:credentail forAuthenticationChallenge:challenge];
}

リンク

参考またはこうすべきサイト

サンプルコード

//
// Description
// ----------------
//
// This is sample for handle self sigined certificate.
//
// This code have 3 way for building.
//
// - Default : Can't connect self signed certificate server.
// - AUTH : Can connect self signed certificate server by old style.
// - AUTH_NEW : Can connect self signed certificate server by new style.
//
// Command usage
// ----------------
//
// ./urlcon http(s)://xxxxx.com/
//
//
// Compile command
// ----------------
//
// Default : not handle authenticate
//
// clang -g -Wall -fobjc-arc -o urlcon web.m -framework Foundation
//
//
// AUTH : handle old style
//
// clang -g -Wall -fobjc-arc -o urlcon web.m -framework Foundation -DAUTH
//
//
// AUTH_NEW : handle new style
//
// clang -g -Wall -fobjc-arc -o urlcon web.m -framework Foundation -DAUTH_NEW
//
//
// Note
// ------
//
// Perhaps iOS 5 can't support DSA signature algorism.
// Mac is running this code.
//
//
#import <Foundation/Foundation.h>
@interface HTTP : NSObject <NSURLConnectionDelegate>
{
BOOL finished;
}
@property (nonatomic) BOOL ssl;
-(void) connect:(NSString*)url;
@end
@implementation HTTP
@synthesize ssl;
-(id) init {
if ((self = [super init]) != nil) {
finished = NO;
}
return self;
}
-(void) connect:(NSString*)url {
NSMutableString* urlString = [NSMutableString stringWithCapacity:128];
[urlString appendString:url];
NSLog(@"URL[%@]", urlString);
[NSURLConnection connectionWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:urlString]] delegate: self];
NSRunLoop* loop = [NSRunLoop currentRunLoop];
while (finished == NO && [loop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture] ]);
}
#pragma mark --
#pragma mark Delegate
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
NSLog(@"000>%@", response);
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
NSLog(@"--->: %@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
finished = YES;
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
finished = YES;
NSLog(@"err->%@", error);
}
#ifdef AUTH
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace {
return YES;
}
- (BOOL)connectionShouldUseCredentialStorage:(NSURLConnection *)connection {
return YES;
}
- (void) connection:(NSURLConnection *)conn didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
NSURLProtectionSpace * protectionSpace = [challenge protectionSpace];
NSURLCredential* credentail = [NSURLCredential credentialForTrust:[protectionSpace serverTrust]];
[[challenge sender] useCredential:credentail forAuthenticationChallenge:challenge];
}
#endif
#ifdef AUTH_NEW
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
NSURLProtectionSpace * protectionSpace = [challenge protectionSpace];
NSURLCredential* credentail = [NSURLCredential credentialForTrust:[protectionSpace serverTrust]];
[[challenge sender] useCredential:credentail forAuthenticationChallenge:challenge];
}
#endif
@end
int main(int argc, char* argv[]) {
@autoreleasepool {
NSString* url = [NSString stringWithCString:argv[1] encoding:NSUTF8StringEncoding];
HTTP* https = [[HTTP alloc] init];
[https connect:url];
}
return 0;
}
view raw web.m hosted with ❤ by GitHub