[android] AsyncTask too late problem..

안드로이드 AsyncTask

android AsyncTask 는 안드로이드에서 자주쓰고, 자주 보는 클래스이다.

우리 회사에서 서비스중인 안드로이드 앱에서도 AsyncTask를 많이 쓰고 있다.

그런데, 회사에서 서비스 중인 안드로이드가 너무 느려서 원인을 찾기위해 이것저것 로그를 찍어본 결과.
AsyncTask를 실행하고, doInBackground() 호출이 너무 느렸다. 무려 3초에서 4초정도 딜레이가 되고 있었다.

원인을 열심히 찾아봤는데 허니콤 이전 버전에선 AsyncTask의 개수제한이 있었다.

core pool size와 max pool size가 있었던것 같은데, 필요하면 아래 글 참고 하면 될듯.

AsyncTask 참고1
AsyncTask 참고2

수정하려고 봤더니 여기저기 AsyncTask를 마구마구 쓰고 있고, 여러 depth에 걸처서 부르는 로직도 있어서 수정 규모가 너무 크다고 판단.

일단 심플하게 thread를 이용해서 AsyncTask역할을 그대로 하는 코드를 만들었다.

Why?

AsyncTask 자리에 그대로 바꿔치기 하기 위함이다.
일단 이것으로 속도확보를 했으니 다음 차례는 쓰레드 풀이든 스케쥴링이던 하면 될 듯하고. 일단 지금은 스케쥴러를 별도로 만들어 관리하도록 수정.

혹시 몰라서 여기에 올려놓는다. 자료 백업 목적 및 필요한 사람들이 있을지도 모르니 공유의 목적도…

/****
 * title: AsyncThread
 * description: Simple thread extension like AsyncTask. 
 * 				But the AsyncThread is non atomic no use thread pool.
 *
 * author: weep
 * blog: weeppp.com
 * email: ktg@weeppp.com
 * Copyright (c) 2015 Teukgeon, Kwon. All rights reserved.
 ****/

package com.weeppp.tklib;

import android.os.Handler;
import android.os.Message;

public abstract class AsyncThread<Params, Progress, Result> extends Thread implements Runnable {
    protected void onPreExecute() {};
    abstract protected Result doInBackground(Params... params);
    protected void onPostExecute(Result result) {};
    protected void onCancell() {};

    Params[] params;
    static final int MESSAGE_POST_RESULT = 30;

    enum Status {
        PENDING,
        RUNNING,
        FINISHED
    }

    private Status status = Status.PENDING;
    private boolean isCancel = false;
    final InternalHandler internalHandler = new InternalHandler();

    public AsyncThread()
    {

    }

    public AsyncThread<Params, Progress, Result> execute(Params... params)
    {
        if (status != Status.PENDING) {
            switch (status) {
                case RUNNING:
                    throw new IllegalStateException("Cannot execute task:"
                            + " the task is already running.");
                case FINISHED:
                    throw new IllegalStateException("Cannot execute task:"
                            + " the task has already been executed "
                            + "(a task can be executed only once)");
                default:
                    break;
            }
        }
        status = Status.RUNNING;

        this.params = params;
        onPreExecute();
        start();
        return this;
    }

    public final Status getStatus() {
        return status;
    }

    public final boolean isCancelled() {
        return isCancel;
    }

    public final boolean cancel() {
        isCancel = true;
        return isCancel;
    }

    public final boolean cancel(boolean mayInterruptIfRunning) {
        isCancel = true;
        return isCancel;
    }

    public void run()
    {
        final Result result = doInBackground(params);

        Message msg = internalHandler.obtainMessage(MESSAGE_POST_RESULT);
        msg.obj = new AsyncResult(this, result);
        internalHandler.sendMessage(msg);
    }

    protected void onCancell(Result result)
    {
        onCancell();
    }

    private void finish(Result result)
    {
        if (isCancelled()) {
            onCancell(result);
        }
        else {
            onPostExecute(result);
        }
        status = Status.FINISHED;
    }

    private static class InternalHandler extends Handler {
        @SuppressWarnings({"unchecked"})
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MESSAGE_POST_RESULT:
                    AsyncResult aResult = (AsyncResult)msg.obj;
                    aResult.thread.finish(aResult.result);
                    break;
            }
        }
    }

    @SuppressWarnings({"rawtypes"})
    static class AsyncResult {
        final AsyncThread thread;
        final Object result;
        public AsyncResult(AsyncThread thread, Object result)
        {
            this.thread = thread;
            this.result = result;
        }
    }
}

MariaDB 설치 하기 for CentOS 6.4

MariaDB 설치 하기 for CentOS 6.4

mysql 버전이 5.1이어서 버전업을 마음먹었다.
그런데 5.6으로 올리느니 마리아DB로 갈아타고 싶어졌다.

자 마리아 DB를 설치하자.

1. 기존 mysql을 제거한다.

yum remove mysql mysql-server

2. 기존 mysql 디렉토리를 제거한다. 여기서는 백업을 해뒀다. 워드프레스 db를 살릴려고~

cp -rf /var/lib/mysql /var/lib/mysql_
rm -rf /var/lib/mysql

3. Maria DB의 yum설치를 위해서 repository 파일 추가를 한다.
공식사이트를 참고하자.

vi /etc/yum.repos.d/MariaDB.repo

4. 아래 내용 파일에 추가.

[mariadb]
name = MariaDB
baseurl = http://yum.mariadb.org/10.0/centos6-amd64
gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
gpgcheck=1

5. install MariaDB
아래 Maria-devel은 개발용이다. 필요없으면 설치하지 말자.

sudo yum install MariaDB-server MariaDB-client MariaDB-devel

6. maria db server 실행

sudo /etc/init.d/mysql restart

7. maria db 접속 확인

mysql -uroot

ps. 나처럼 기존 mysql database가 있는 경우는 아까 백업해둔 곳에서 db를 카피한다.

cp -rp /var/lib/mysql_backup/database_name /var/lib/mysql
chown -R mysql.mysql /var/lib/mysql/database_name

그대로 db사용이 가능하다. 마리아 db 설치 끝.

[python] 파이썬 2.7 용 pip 설치하기

python pip install for CentOS

python 2.7.6을 centos 6.5에 설치했다.
파이썬 2.7.6 centos에 설치하기

이제 장고를 설치하려는데 일단 패키지 매니저(pip)부터 설치를 해보자

파이썬 패키지 매니저를 설치하기 앞서 sudo 했을 때 PATH를 확인하자.

sudo env |grep PATH

/usr/local/bin이 없으면 아래 내용을 /etc/profile에 추가하고 shell을 재실행한다.

vi /etc/profile
alias sudo='sudo env PATH=$PATH'
wget http://peak.telecommunity.com/dist/ez_setup.py
sudo python ez_setup.py
sudo easy_install pip

pip를 실행해보자.

[python] 파이썬 2.7.6 설치 with CentOS 6.5

centos에 파이썬이 기본적으로 설치되어 있는데 버전이 2.6이다.
파이썬 2.7을 설치해보자.

파이썬 설치를 해보자.
python 2.7.6 install with CentOS 6.5

먼저 필요 라이브러리 설치

yum groupinstall "Development tools"
yum install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel db4-devel libpcap-devel xz-devel

wget으로 파이썬 설치파일 다운로드

wget http://python.org/ftp/python/2.7.6/Python-2.7.6.tar.xz

xz파일이다. xz 압축을 풀기위해서 xz설치

yum install xz

압축 해제

tar xvfJ Python-2.7.6.tar.xz

폴더 이동.

cd Python-2.7.6.tar.xz

빌드하자

./configure --prefix=/usr/local --enable-unicode=ucs4 --enable-shared LDFLAGS="-Wl,-rpath /usr/local/lib"
make
sudo make altinstall

파이썬 설치 완료

이제 PATH를 확인하자.

env | grep PATH

기본으로 /usr/local/bin이 /usr/bin보다 앞에 나와있다.

기존 파이썬이 설치된 디렉토리로 이동

cd /usr/bin

기존 파이썬 파일명 변경

sudo mv python python.old

리눅스 터미널에 재접속해서 python 2.7이 정상적으로 설치되었는지 확인

python
Python 2.7.6 (default, Apr 27 2015, 17:35:43)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-11)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>

ruby rbenv install 2.0.0-p247 fail for Centos

rbenv 를 이용해서 ruby 2.0.0 p247을 설치할 때 에러가 발생한다. centos 6.5에서 발생했다.

해결법을 기록해둔다. 참고가 되길 바란다.

ref web site

rbenv install 2.0.0-p247

위의 명령을 실행했을 때 아래 상황 발생

problem:

BUILD FAILED

Inspect or clean up the working tree at /tmp/ruby-build.20150424111036.5089
Results logged to /tmp/ruby-build.20150424111036.5089.log

Last 10 log lines:
ossl_pkey_ec.c:821: error: for each function it appears in.)
make[2]: *** [ossl_pkey_ec.o] Error 1
make[2]: Leaving directory `/tmp/ruby-build.20150424111036.5089/ruby-2.0.0-p247/ext/openssl'
make[1]: *** [ext/openssl/all] Error 2
make[1]: *** Waiting for unfinished jobs....
installing default callback libraries
linking shared-object dl/callback.so
make[2]: Leaving directory `/tmp/ruby-build.20150424111036.5089/ruby-2.0.0-p247/ext/dl/callback'
make[1]: Leaving directory `/tmp/ruby-build.20150424111036.5089/ruby-2.0.0-p247'
make: *** [build-ext] Error 2

solution:

1. Create “patch.diff” file.
2. Copy the content below.

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 41807)
+++ ChangeLog	(revision 41808)
@@ -1,3 +1,16 @@
+Sat Jul  6 07:37:43 2013  Martin Bosslet  <Martin.Bosslet@gmail.com>
+
+	* ext/openssl/ossl_pkey_ec.c: Ensure compatibility to builds of
+	  OpenSSL with OPENSSL_NO_EC2M defined, but OPENSSL_NO_EC not
+	  defined.
+	* test/openssl/test_pkey_ec.rb: Iterate over built-in curves
+	  (and assert their non-emptiness!) instead of hard-coding them, as
+	  this may cause problems with respect to the different availability
+	  of individual curves in individual OpenSSL builds.
+	  [ruby-core:54881] [Bug #8384]
+
+	  Thanks to Vit Ondruch for providing the patch!
+
 Sat Jul  6 07:12:39 2013  Martin Bosslet  <Martin.Bosslet@gmail.com>
 
 	* test/openssl/test_x509crl.rb: Remove unused variable.
Index: ext/openssl/ossl_pkey_ec.c
===================================================================
--- ext/openssl/ossl_pkey_ec.c	(revision 41807)
+++ ext/openssl/ossl_pkey_ec.c	(revision 41808)
@@ -762,8 +762,10 @@
                 method = EC_GFp_mont_method();
             } else if (id == s_GFp_nist) {
                 method = EC_GFp_nist_method();
+#if !defined(OPENSSL_NO_EC2M)
             } else if (id == s_GF2m_simple) {
                 method = EC_GF2m_simple_method();
+#endif
             }
 
             if (method) {
@@ -817,8 +819,10 @@
 
             if (id == s_GFp) {
                 new_curve = EC_GROUP_new_curve_GFp;
+#if !defined(OPENSSL_NO_EC2M)
             } else if (id == s_GF2m) {
                 new_curve = EC_GROUP_new_curve_GF2m;
+#endif
             } else {
                 ossl_raise(rb_eArgError, "unknown symbol, must be :GFp or :GF2m");
             }
Index: test/openssl/test_pkey_ec.rb
===================================================================
--- test/openssl/test_pkey_ec.rb	(revision 41807)
+++ test/openssl/test_pkey_ec.rb	(revision 41808)
@@ -7,28 +7,28 @@
     @data1 = 'foo'
     @data2 = 'bar' * 1000 # data too long for DSA sig
 
-    @group1 = OpenSSL::PKey::EC::Group.new('secp112r1')
-    @group2 = OpenSSL::PKey::EC::Group.new('sect163k1')
-    @group3 = OpenSSL::PKey::EC::Group.new('prime256v1')
+    @groups = []
+    @keys = []
 
-    @key1 = OpenSSL::PKey::EC.new
-    @key1.group = @group1
-    @key1.generate_key
+    OpenSSL::PKey::EC.builtin_curves.each do |curve, comment|
+      group = OpenSSL::PKey::EC::Group.new(curve)
 
-    @key2 = OpenSSL::PKey::EC.new(@group2.curve_name)
-    @key2.generate_key
+      key = OpenSSL::PKey::EC.new(group)
+      key.generate_key
 
-    @key3 = OpenSSL::PKey::EC.new(@group3)
-    @key3.generate_key
-
-    @groups = [@group1, @group2, @group3]
-    @keys = [@key1, @key2, @key3]
+      @groups << group
+      @keys << key
+    end
   end
 
   def compare_keys(k1, k2)
     assert_equal(k1.to_pem, k2.to_pem)
   end
 
+  def test_builtin_curves
+    assert(!OpenSSL::PKey::EC.builtin_curves.empty?)
+  end
+
   def test_curve_names
     @groups.each_with_index do |group, idx|
       key = @keys[idx]

3. Create “fedora.configure” file
4. Copy the content below.

#!/bin/sh
patch -p0 -i /tmp/patch.diff
exec ./configure "$@"

5. Execute this command.

RUBY_CONFIGURE=/home/user/fedora-configure rbenv install 2.0.0-p247

6. check ruby version.

rbenv versions

RVM install for multi user

How to install RVM for multi user.

RVM 설치하기
참고:

다중사용자 설정

sudo curl -sSL https://get.rvm.io | sudo bash -s stable

아래 내용처럼 나올 경우

Downloading https://github.com/rvm/rvm/archive/1.26.11.tar.gz
Downloading https://github.com/rvm/rvm/releases/download/1.26.11/1.26.11.tar.gz.                                    asc
gpg: Signature made Tue 31 Mar 2015 06:52:13 AM KST using RSA key ID BF04FF17
gpg: Can't check signature: No public key
Warning, RVM 1.26.0 introduces signed releases and automated check of signatures                                     when GPG software found.
Assuming you trust Michal Papis import the mpapis public key (downloading the si                                    gnatures).

GPG signature verification failed for '/usr/local/rvm/archives/rvm-1.26.11.tgz'                                     - 'https://github.com/rvm/rvm/releases/download/1.26.11/1.26.11.tar.gz.asc'!
try downloading the signatures:

    sudo gpg2 --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A170                                    3113804BB82D39DC0E3

or if it fails:

    command curl -sSL https://rvm.io/mpapis.asc | sudo gpg2 --import -

the key can be compared with:

    https://rvm.io/mpapis.asc
    https://keybase.io/mpapis

공개키가 없다고 하니 공개키를 받아줘야할 듯.
콘솔 창에 나온데로 실행한다.

sudo gpg2 --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3

그리고 다시 첫번째 명령 실행

rvm이 잘 설치되었는지 아래 명령을 통해 확인한다.

type rvm | head -n 1

rvm is a function
이라고 나오면 정상

rvm을 사용할 계정을 rvm group에 포함시킨다.

sudo vi /etc/group

...

rvm:x:505:user,user2,user3

이제 rvm을 사용할 계정으로 다시 로그인 한다.
로그인을 다시 하는 이유는 rvm이 로그인 시간정보를 가지고 유효한 유저인지 판별하기 때문인 듯 하다. 공식사이트에서 확인해보시길.

설치 가능 목록 확인

rvm list known

2.0.0 설치

rvm install 2.0.0

여러 유저가 사용하므로 ruby에서 참조하는 gem을 다르게 할 수 있다.

rvm use 2.0.0@newgemset --create --default

newgemset 이라는 gem set을 만들어서 기본으로 사용하라는 명령이다. 이름은 마음대로 바꾸자.

나만의 Git 서버 설정하기

나만의 기트 서버를 설치해보자. ssh와 연동하기

 

Git server 설정하기.

 

centos 에 설치하기

git server 의존 패키지 설치

yum install curl-devel expat-devel gettext-devel \
  openssl-devel zlib-devel

git 설치

yum install git-core

리눅스에 git 계정 만들기

adduser git
passwd git
cd /opt
mkdir git
chown git.git git
cd /opt/git
sudo vi ReadMe

아래 내용을 위의 ReadMe파일에 넣어두고 앞으로 쭉 사용하자~

#create repository
git init --bare --shared my_project.git
chown -R git.git my_project.git

모든 유저들이 서버에 저장할 때 git계정을 이용할 수 있도록 설정해준다.

sudo vi /etc/passwd

위 명령 후 아래 내용을 찾는다.

git:x:502:503::/home/git:/bin/bash
which git-shell

명령으로 git-shell 위치를 확인한다.

/bin/bash 를 위에 나온 결과값(여기서는 /usr/bin/git-shell)로 변경한다

변경 후 부터는 git 계정은 Git 저장소에 Push하고 Pull하는 것만 가능하고 리눅스의 쉘에는 접근할 수 없다.

——– 샘플 프로젝트 설정 ——–

서버 설정이 끝났으니 샘플 프로젝트를 하나 만들어보자.

방금 만들었던 ReadMe를 읽고 아래 명령을 처보자.

cd /opt/git
sudo git init --bare --shared my_project.git
sudo chown -R git.git my_project.git

클리이언트에서 나의 git 서버와 연동을 해본다.

SourceTree를 사용할 경우
“복제 / 생성” -> “소스 경로 / URL” 에 아래 값 입력

ssh://git@weeppp.com/opt/git/my_project.git

포트가 다를 경우
ssh://git@weeppp.com:[PORT]/opt/git/my_project.git

이제 git를 이용하면 된다.

미래 연봉 계산기 (향후 나의 연봉은?)

자신의 미래 연봉은 얼마나 될까요?
연봉 인상률을 이용해서 연봉 계산기를 심플하게 만들어 봤습니다.

 

현재 연봉(만원)
연봉 인상률(%)
몇년 뒤?(년)

결과(만원)

[centos] svn server(subversion) 아파치 https 연동하기

예전부터 종종 해오면서 “해야지, 해야지”했던 svn 서버 설정에 대해 블로깅하려 한다.

지금은 git가 대세라서 git도 좀 써보려하지만 일단 친숙한 svn서버 설정부터 해놓으려는게 목적이다.

서버 환경은 Centos 6.5 이고 minimun을 다운받아서 기본만 설치한 상태이다.

1. 아파치 설치

$> sudo yum install httpd

a. 정상설치 확인

$> rpm -qa httpd
httpd-2.2.15-39.el6.centos.x86_64

b. 아파치 iptables 예외 설정

$>sudo vi /etc/sysconfig/iptables

아래 내용 추가

-A INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 443 -j ACCEPT

아파치 svn연동 모듈 설치

$> sudo yum install mod_dav_svn mod_ssl

 

2. 아파치 https 설정

https 키생성(self signing)

$> openssl genrsa -des3 -out cert.key 1024
$> openssl req -new -key cert.key -out cert.csr
$> openssl x509 -req -days 3650 -in cert.csr -signkey cert.key -out cert.crt

키를 특정 경로에 저장, 여기서는 /etc/httpd폴더에 cert폴더를 만듬

$> mkdir /etc/httpd/cert

httpd-svn.conf파일을 /etc/httpd/conf.d/ 경로에 생성 한 뒤,

$> vi /etc/httpd/conf.d/httpd-svn.conf

 

아래 내용을 자신에게 맞도록 설정을 변경한다.

ServerName: 본인의 서버 이름

ServerAlias: 서버의 약칭

AuthUserFile: svn의 repository의 유저 패스워드 파일(뒤에 생성)

AuthzSVNAccessFile: svn의 repository 각 프로젝트의 권한 설정 파일(뒤에 생성)

SSLCertificateFile: 생성한 인증서파일

SSLCertificateKeyFile: 생성한 개인키

<VirtualHost *:443>

ServerName weeppp.com
ServerAlias weeppp.com
DocumentRoot "/var/www/svn"

<Location /test>
    DAV                svn
#   SVNPath             "/repository/sample"
    SVNParentPath      "/repository"
    SVNListParentPath  On
    SVNIndexXSLT       "/repos-web/view/repos.xsl"

    AuthType           Basic
    AuthName           "SVN Repository"
    AuthUserFile       "/repository/.passwd"
    AuthzSVNAccessFile "/repository/.authz"
    Require            valid-user
</Location>

# Use separate log files for the SSL virtual host; note that LogLevel
# is not inherited from httpd.conf.
ErrorLog logs/ssl_error_log
TransferLog logs/ssl_access_log
LogLevel warn

#   SSL Engine Switch:
#   Enable/Disable SSL for this virtual host.
SSLEngine on

#   SSL Protocol support:
# List the enable protocol levels with which clients will be able to
# connect.  Disable SSLv2 access by default:
SSLProtocol all -SSLv2

#   SSL Cipher Suite:
# List the ciphers that the client is permitted to negotiate.
# See the mod_ssl documentation for a complete list.
SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW

#   Server Certificate:
# Point SSLCertificateFile at a PEM encoded certificate.  If
# the certificate is encrypted, then you will be prompted for a
# pass phrase.  Note that a kill -HUP will prompt again.  A new
# certificate can be generated using the genkey(1) command.
#SSLCertificateFile /etc/pki/tls/certs/localhost.crt
SSLCertificateFile /etc/cert/server.crt

#   Server Private Key:
#   If the key is not combined with the certificate, use this
#   directive to point at the key file.  Keep in mind that if
#   you've both a RSA and a DSA private key you can configure
#   both in parallel (to also allow the use of DSA ciphers, etc.)
#SSLCertificateKeyFile /etc/pki/tls/private/localhost.key
SSLCertificateKeyFile /etc/cert/server.key

#   Server Certificate Chain:
#   Point SSLCertificateChainFile at a file containing the
#   concatenation of PEM encoded CA certificates which form the
#   certificate chain for the server certificate. Alternatively
#   the referenced file can be the same as SSLCertificateFile
#   when the CA certificates are directly appended to the server
#   certificate for convinience.
#SSLCertificateChainFile /etc/pki/tls/certs/server-chain.crt

#   Certificate Authority (CA):
#   Set the CA certificate verification path where to find CA
#   certificates for client authentication or alternatively one
#   huge file containing all of them (file must be PEM encoded)
#SSLCACertificateFile /etc/pki/tls/certs/ca-bundle.crt

#   Client Authentication (Type):
#   Client certificate verification type and depth.  Types are
#   none, optional, require and optional_no_ca.  Depth is a
#   number which specifies how deeply to verify the certificate
#   issuer chain before deciding the certificate is not valid.
#SSLVerifyClient require
#SSLVerifyDepth  10

#   Access Control:
#   With SSLRequire you can do per-directory access control based
#   on arbitrary complex boolean expressions containing server
#   variable checks and other lookup directives.  The syntax is a
#   mixture between C and Perl.  See the mod_ssl documentation
#   for more details.
#<Location />
#SSLRequire (    %{SSL_CIPHER} !~ m/^(EXP|NULL)/ \
#            and %{SSL_CLIENT_S_DN_O} eq "Snake Oil, Ltd." \
#            and %{SSL_CLIENT_S_DN_OU} in {"Staff", "CA", "Dev"} \
#            and %{TIME_WDAY} >= 1 and %{TIME_WDAY} <= 5 \
#            and %{TIME_HOUR} >= 8 and %{TIME_HOUR} <= 20       ) \
#           or %{REMOTE_ADDR} =~ m/^192\.76\.162\.[0-9]+$/
#</Location>

#   SSL Engine Options:
#   Set various options for the SSL engine.
#   o FakeBasicAuth:
#     Translate the client X.509 into a Basic Authorisation.  This means that
#     the standard Auth/DBMAuth methods can be used for access control.  The
#     user name is the `one line' version of the client's X.509 certificate.
#     Note that no password is obtained from the user. Every entry in the user
#     file needs this password: `xxj31ZMTZzkVA'.
#   o ExportCertData:
#     This exports two additional environment variables: SSL_CLIENT_CERT and
#     SSL_SERVER_CERT. These contain the PEM-encoded certificates of the
#     server (always existing) and the client (only existing when client
#     authentication is used). This can be used to import the certificates
#     into CGI scripts.
#   o StdEnvVars:
#     This exports the standard SSL/TLS related `SSL_*' environment variables.
#     Per default this exportation is switched off for performance reasons,
#     because the extraction step is an expensive operation and is usually
#     useless for serving static content. So one usually enables the
#     exportation for CGI and SSI requests only.
#   o StrictRequire:
#     This denies access when "SSLRequireSSL" or "SSLRequire" applied even
#     under a "Satisfy any" situation, i.e. when it applies access is denied
#     and no other module can change it.
#   o OptRenegotiate:
#     This enables optimized SSL connection renegotiation handling when SSL
#     directives are used in per-directory context.
#SSLOptions +FakeBasicAuth +ExportCertData +StrictRequire
<Files ~ "\.(cgi|shtml|phtml|php3?)$">
    SSLOptions +StdEnvVars
</Files>
<Directory "/var/www/cgi-bin">
    SSLOptions +StdEnvVars
</Directory>

#   SSL Protocol Adjustments:
#   The safe and default but still SSL/TLS standard compliant shutdown
#   approach is that mod_ssl sends the close notify alert but doesn't wait for
#   the close notify alert from client. When you need a different shutdown
#   approach you can use one of the following variables:
#   o ssl-unclean-shutdown:
#     This forces an unclean shutdown when the connection is closed, i.e. no
#     SSL close notify alert is send or allowed to received.  This violates
#     the SSL/TLS standard but is needed for some brain-dead browsers. Use
#     this when you receive I/O errors because of the standard approach where
#     mod_ssl sends the close notify alert.
#   o ssl-accurate-shutdown:
#     This forces an accurate shutdown when the connection is closed, i.e. a
#     SSL close notify alert is send and mod_ssl waits for the close notify
#     alert of the client. This is 100% SSL/TLS standard compliant, but in
#     practice often causes hanging connections with brain-dead browsers. Use
#     this only for browsers where you know that their SSL implementation
#     works correctly.
#   Notice: Most problems of broken clients are also related to the HTTP
#   keep-alive facility, so you usually additionally want to disable
#   keep-alive for those clients, too. Use variable "nokeepalive" for this.
#   Similarly, one has to force some clients to use HTTP/1.0 to workaround
#   their broken HTTP/1.1 implementation. Use variables "downgrade-1.0" and
#   "force-response-1.0" for this.
SetEnvIf User-Agent ".*MSIE.*" \
         nokeepalive ssl-unclean-shutdown \
         downgrade-1.0 force-response-1.0

#   Per-Server Logging:
#   The home of a custom SSL log file. Use this when you want a
#   compact non-error SSL logfile on a virtual host basis.
CustomLog logs/ssl_request_log \
          "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"

</VirtualHost>

 

 

아파치 설정 폴더로 이동

$> cd /etc/httpd/conf

설정 파일 오픈 및 내용 변경

  • 서버이름은 해당 도메인이나 아이피등으로 변경
  • User와 Group은 아래와 같이 아파치로 변경
ServerName weeppp.com
User apache
Group apache

/etc/httpd/conf 디렉토리에 extra 폴더 생성 및 파일 생성

$> mkdir extra
$> cd extra
$> vi httpd-svn.conf

httpd-svn.conf 파일안에 아래 내용 복사

##############################################################
# SVN
##############################################################

LoadModule dav_svn_module   modules/mod_dav_svn.so
LoadModule authz_svn_module modules/mod_authz_svn.so

<VirtualHost *:443>
    ServerName  weeppp.com
    ServerAlias  weeppp.com
    DocumentRoot "/data/webapps/svn/public_html"
    ServerAdmin  admin@gmail.com

    SetEnvIf Request_URI "\.(gif)|(jpg)|(swf)|(png)$" image_log

    CustomLog    "logs/svn_access_log.log"       common env=!image_log
    CustomLog    "logs/svn_access_image_log.log" common env=image_log
    ErrorLog     "logs/svn_error_log.log"

    <Location /svn>
        DAV                svn
        #SVNPath             "/repository/svn/repo/devsample"
        SVNParentPath /repository
#        SVNParentPath      "/repository/svn/devsample"
#        SVNListParentPath  On
        SVNIndexXSLT       "/repos-web/view/repos.xsl"

        AuthType           Basic
        AuthName           "Weep SVN Repository"
        AuthUserFile       "/repository/.passwd"
        AuthzSVNAccessFile "/repository/.authz"
        Require            valid-user
    </Location>
</VirtualHost>

여기서는 SVNParentPath를 설정해줘서 루트아래의 모든 프로젝트를 접근 가능하도록 함

3. SVN 설정

svn 저장소를 원하는 경로에 생성 및 이동

$> mkdir /repository
$> cd /repository

svn 저장소 소유자 변경

$> chown -R apache.apache /repository

sample프로젝트 생성

$> svnadmin create /repository/sample

프로젝트 소유자 및 권한 변경

$> chown -R apache.apache sample
$> chcon -R -t httpd_sys_content_t sample

svn 계정생성

$> htpasswd -c -m .passwd USER

.authz파일 생성

$> vi /repository/.authz

.authz파일에 하단 내용 추가

admin 그룹에 속한 계정(현재는 weeppp)에게 sample 프로젝트의 read/write 권한을 모두 주는것을 의미한다.

[groups]
admin=weeppp

[sample:/]
@admin = rw

 

.passwd 파일과 .authz파일 소유자를 apache로 변경한다

$> chown apache.apache .passwd
$> chown apache.apache .authz

problems with SELinux context/lables 요 문제가 있으므로 아래 명령을 실행한다.

$> chcon -t httpd_sys_content_t .authz
$> chcon -t httpd_sys_content_t .passwd

위의 명령어들을 잊지 않도록 /repository 폴더안에 ReadMe 파일로 저장해둔다.

#user create
htpasswd -c -m .passwd USER
#user add
htpasswd -m .passwd USER

#create svn repository
svnadmin create /repository/sample
chown -R apache.apache sample
chcon -R -t httpd_sys_content_t sample

subversion 재시작

$> /etc/init.d/svnserve stop
$> /etc/init.d/svnserve start

아파치 재시작

$> /etc/init.d/httpd restart

svn client를 이용해서 서버에 접근해본다.

https://weeppp.com/test/sample

checkout 하고 인증 받은 뒤에 svn을 이용하면 된다.

 

 

 

[tip] jquery input text에 숫자나 알파벳만 입력 받기

jquery 를 이용해서 html input tag에 숫자와 알파벳만 입력받도록 만든다.

웹 개발을 하다보면 인풋태그에 원하는 값만을 입력 받고 싶을 때가 있다.

현재 게임 운영툴을 개발하면서 숫자만 입력 받고 싶은 경우가 생겼다.

라이브러리를 찾아보았으나 한글이 입력되거나 특수문자가 입력되는 경우가 발생했다.

그래서 기존 라이브러리에 코드를 추가해서 한글이나 특수문자를 막고 숫자만 입력받는 로직을 만들었다.

필요하신분은 참고 하시길.

참고로 숫자입력만 허용하는 로직만 테스트된 상태며, 테스트는 구글 크롬에서만 하였다. (현재 운영툴이 크롬을 대상으로 개발하고 있기 때문)
익스플로러에서는 안됐던 듯 싶다.

사용법은 아래 링크타고 가서 원래 라이브러리파일을 다운 받으면 index.html에 상세히 있다.

https://github.com/johnantoni/jquery.alphanumeric

수정한 코드.

(function($){

	$.fn.alphanumeric = function(p) { 

		p = $.extend({
			ichars: "!@#$%^&*()+=[]\\\';,/{}|\":<>?~`.-_ ",
			nchars: "",
			allow: ""
		  }, p);	

		return this.each
			(
				function() 
				{

					if (p.nocaps) p.nchars += "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
					if (p.allcaps) p.nchars += "abcdefghijklmnopqrstuvwxyz";

					s = p.allow.split('');
					for ( i=0;i<s.length;i++) if (p.ichars.indexOf(s[i]) != -1) s[i] = "\\" + s[i];
					p.allow = s.join('|');

					var reg = new RegExp(p.allow,'gi');
					var ch = p.ichars + p.nchars;
					ch = ch.replace(reg,'');

					$(this).keydown
						(
							function (e)
								{

									if (!e.charCode) k = String.fromCharCode(e.which);
										else k = String.fromCharCode(e.charCode);
									// Korean filtering,  modified by ktg. 
									// if (k.charCodeAt(0) == 229) e.preventDefault();
									// exception not ascii code, and shift + number keys
									if (33 <= e.which && e.which <= 40) return;
									// 컨트롤 c,v,x,a는 허용
									if (e.ctrlKey && (k.match(/(c|v|x|a)/i) != null)) return;
									// 아스키코드 이외의 글자는 막기
									if (k.charCodeAt(0) > 127) e.preventDefault();
									// 특수문자 막기
									if (e.shiftKey&&k.match(/\d+/g)!=null) e.preventDefault();

									if (ch.indexOf(k) != -1) e.preventDefault();
									if (e.ctrlKey&&k=='v') e.preventDefault();

								}

						);

					$(this).bind('contextmenu',function () {return false});

				}
			);

	};

	$.fn.numeric = function(p) {

		var az = "abcdefghijklmnopqrstuvwxyz";
		az += az.toUpperCase();

		p = $.extend({
			nchars: az
		  }, p);	

		return this.each (function()
			{
				$(this).alphanumeric(p);
				// 복사 붙여넣기 방지 로직
				$(this).keyup
					(
						function (e)
							{
								var newVal = $(this).val().replace(/[^0-9\s]/gi,"");
								if (newVal != $(this).val()) {
									$(this).val( $(this).val().replace(/[^0-9\s]/gi,"") );
								}
							}
					);
			}
		);

	};

	$.fn.alpha = function(p) {

		var nm = "1234567890";

		p = $.extend({
			nchars: nm
		  }, p);	

		return this.each (function()
			{
				$(this).alphanumeric(p);
			}
		);

	};	

})(jQuery);