안주꺼리 2010/07/14 14:02
  • 글라스우드 - 난연, 무독성, 방부, 방충, 치수안정성, 강도, 내구성 등 탁월한 성능을 발휘하도록 만든 불용성 목재
  • 텍스트큐브 1.6부터는 단일 블로그의 경우에는 아파치의 mod_rewrite 를 사용하지 않아도 사용이 가능합니다. 이 경우 예쁜 주소 (http://example.com/entry/테스트글) 는 불가능하지만, 거의 비슷한 형식의 주소 (http://example.com/index.php?/entry/테스트글) 로 사용할 수 있습니다.

    이렇게 변경되는 과정에서 텍스트큐브 설치 디렉토리 안의 모든 파일 접근을 텍스트큐브가 관리하기 때문에 기존에 사용하던 텍스트큐브 디렉토리 안의 다른 프로그램 (구글 사이트맵이나 통계용 플러그인) 들이 동작하지 않는 경우가 있습니다. 이 경우에는 텍스트큐브가 설치된 디렉토리 안의 .htaccess의 내용에 몇가지를 추가해서 그 문제를 해결할 수 있습니다.

    예를 들어, 텍스트큐브 루트 디렉토리에 sitemap.php가 있는 경우 웹 주소를 통해서 접근하도록 하기 위해서는RewriteBase / 줄 바로 아랫줄에 다음의 두 줄을 추가합니다.

    RewriteCond %{REQUEST_FILENAME} -f
    RewriteRule ^(sitemap\.php) sitemap.php [L]

    첫번째 줄은 그 아랫줄이 실행되기 위한 조건입니다. '만약 요청한 파일이 있다면'의 의미입니다. -f는 파일, -d는 디렉토리입니다. 그 다음줄은 '^(sitemap.php) 이 있으면 뒤의 파일로 이동하고 종료하라' 의 의미입니다. ^()은 정규식인데, 정규식에 관해서는 creorix님이 작성하시는 정규식 강좌를 참조하시면 됩니다.

    응용해서, 두 개 이상의 파일일 경우를 작성해 보겠습니다.

    RewriteCond %{REQUEST_FILENAME} -f
    RewriteRule ^(sitemap\.php|statistics\.php) $1 [L]

    sitemap.php이나 statistics.php가 있으면 그 파일을 실행하라~ 는 의미입니다. 정규식 대응때 $1, $2는 앞에 나온 조건의 괄호 하나하나에 차례대로 대응이 됩니다.

    참 쉽죠?




    Rewrite Rule 바뀐 Textcube 1.6 에서 Trace Watch 사용하기

    텍스트큐브 1.6 을 Document Root 에 설치한 경우 Trace Watch 를 정상적으로 사용할 수 없습니다.
    (/blog, /tc 등의 디렉토리에 설치한 경우라면 상관없습니다.)

    TC 1.6 부터 mod_rewrite 관련해서 구조가 바뀌었기 때문이고, 정상적으로 사용을 하기 위해서는 .htaccess 파일을 수정해줘야합니다.

    먼저 수정 방법부터 말쓰드리면,
    .htaccess 파일을 열어서 아래에 bold 로 표시한 부분을 추가해주면 됩니다.

    RewriteEngine On
    RewriteBase /
    RewriteCond %{REQUEST_FILENAME} -d
    RewriteCond %{REQUEST_URI} !^/twatch(/*)
    RewriteRule ^(.+[^/])$ $1/ [L]
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_URI} !^/twatch(/*)
    RewriteRule ^(.*)$ rewrite.php [L,QSA]

    위에 추가한 RewriteCond 은 주소가 /twatch 또는 /twatch/ 인 경우 RewriteRule 을 적용하지 않게 해줍니다.

    그럼, 왜 이렇게 해야하고 바뀐 구조가 무엇인지 살펴보겠습니다.

    TC 1.6 부터는 mod_rewrite 모듈이 설치가 안된 웹서버에서도 사용이 가능하도록 구조의 변경이 있었다고 합니다.
    ( http://www.textcube.org/manual/entry/in ··· textcube (새 창으로 열기) )
     
    기존 버전에서는 URL Rewrite 를 .htaccess 파일에 장황하게 써있는 mod_rewrite 룰에서 처리했었는데
    1.6 부터는 rewrite.php 라는 PHP 파일에서 담당하게 되고,
    .htaccess 파일은 rewrite.php 로 넘겨주는 정도의 역할만 하고 있습니다.
    (mod_rewrite 모듈을 사용하지 않을 경우 index.php 를 통해서 rewrite.php 로 넘어감.)

    이런 구조 변경때문에 .htaccess 의 내용이 바뀌었고 텍스트큐브 안에 따로 만든 디렉토리로 바로 접근이 되지 않게되었습니다.

    Trace Watch 의 경우도 따로 /twatch 등의 디렉토리를 생성해서 설치해야하기 때문에
    텍스트큐브를 Document Root 에 설치한 경우에는 /twatch 로 바로 접근이 되지 않습니다.
    (/twatch/index.php 로는 접근이 되지만 쏘스를 수정하지 않으면 정상적으로 사용이 불가능합니다.)

    그래서 위에 쓴 것과 같이 .htaccess 파일을 수정해야 /twatch 로 바로 접근이 가능해집니다.

    Trace Watch 뿐만 아니라 다른 프로그램 또는 페이지를 만든 경우에도 마찬가지로 적용가능합니다.
    (물론 경우에 따라서 RewriteCond 을 바꿔야합니다.)

    참고 URL
    http://httpd.apache.org/docs/2.0/mod/mod_rewrite.html (새 창으로 열기) : mod_rewrite Documentation

    http://howto.textcube.org/entry/adding- ··· htaccess (새 창으로 열기) : [TC1.6~] 변화된 rewrite 룰에 다른 파일 추가하기

    http://forum.tattersite.com/ko/viewtopic.php?id=4397 (새 창으로 열기) : (질문) 이번에 beta2에서 htaccess가 수정되었는데요

    ※ 추가

    Trace Watch 는 도아님의 플로그인으로 설치를 했었는데, 트랙백 전송이 되지않는 문제가 생겼습니다.

    Trace Watch 플러그인을 켜놓을때만 트랙백 전송이 되지 않아서 원인을 찾아봤는데
    /lib/auth.php 의 requireStrictRoute() 를 통과하지 못해서 'Precondition Failed' 에러가 나고 있었습니다.

    통과 못한 이유는 $_SERVER['HTTP_REFERER'] 가 사라져버렸기 때문인데, 왜 사라졌는지 정확한 이유는 찾지 못했습니다.

    그래서,
    Trace Watch 를 플러그인으로 사용하지 않고 rewrite.php 제일 아래에 코드를 추가해서 일단은 사용가능하도록 해두었습니다.

    Trace Watch 플러그인을 활성화시킬때 왜 referer 가 사라져버리는지... 궁금하네요...

    2010/07/14 14:02 2010/07/14 14:02
    이 글의 관련글

    Trackback Address : http://www.1go.co.kr/blog/trackback/3893

    [로그인][오픈아이디란?]
    안주꺼리 2010/07/14 08:53
  • 글라스우드 - 난연, 무독성, 방부, 방충, 치수안정성, 강도, 내구성 등 탁월한 성능을 발휘하도록 만든 불용성 목재
  • Q&A 에 문의글들이 많아보여...
    간단하게나마 팁을 하나 남깁니다...

    아시는 분들은 이미 아실듯..

    현재 제가 asp -> php 재개발건을 작업중이라 DB이전 작업때문에 현재 사용하고 있는 방법입니다.

    많은 방법이 있겠지만..
    변환 툴을 사용하면, 한글깨짐현상이 발생하기에 추천해 드리지는 않습니다.

    .
    . (잡설 생략)
    .

    제가 활용중인 방법은 freetds.conf 내에 MSSQL 서버를 설정해놓고 해당 정보를 host로 접속하여 DB를 긁어와 MySQL 에 insert 시키고 있습니다.

    apache + php 환경에서 mssql 함수를 사용하기 위해서는 freeTDS 모듈을 설치하여야합니다.
    설치참조 (http://www.freetds.org) 또는 구글링하셔도 많은 정보 얻으실 수 있습니다.

    설치 후 php.ini 의 mssql 관련 부분에 --with-mssql = freeTDS 경로  설정이 되 있어야 정상적으로 가능합니다.


    ------ freetds.conf 파일 설정
    파일 위치 : /usr/local/freetds/etc/freetds.conf  (서버별로 다를 수 있습니다.)

    vi 모드로 여시고..
    아래 부분 설정을 해주시면 freetds 를 활용하여 MSSQL 접속가능합니다.

    [global]
      dump file = 경로/freetds.log  (로그기록 파일)
      client charset = 서버 글자셋 (EUC-KR 또는 UTF-8)

    [test001] - mssql_connect($host,.... ) $host 에 사용할 서버정보
      host = IP 또는 도메인
      port = 1433    (mssql 은 포트 1433 사용)
      tds vercison = freetds 버전정보 입니다.  4.2 / 7.0 / 8.0 등 설정 MSSQL 버전에 따라 사용하시면 됩니다.
      MSSQL 2000 까지는 4.2 로 하시는게 보다 안정적으로 글자안깨지고 넘어오더군요..
     
    [test001] 부분의 설정값을 만약 서버가 여러대라면 추가하시면 되겠죠..



    freetds 의 설치경로는 보통.. /usr/local/freetds 에 위치하며..


    freetds.conf 파일 변경 후 아피치 리스타트 할 필요없습니다. 바로 적용됩니다.

    위까지 다 되었다면.. freetds를 활용하여 mssql 에 접속해봅시다~

    <?php

    $msHost = 'test001';
    $msUser = 'user';
    $msPass = 'password';
    $msDB = 'dbname';


    $myHost = 'localhost';
    $myUser = 'user';
    $myPass = 'password';
    $myDB = 'dbname';

    $msconn = mssql_connect($msHost, $msUser, $msPass);
    mssql_select_db($msDB, $msconn);

    데이터 가져와보기~
    $query = 'select * from table';
    $rst = mssql_query($query);
    while($row=mssql_fetch_array($rst)) {
      데이터 가져오고~
      고대로 MySQL 인서트 해주기~
    }
    ======================================

    간단한 예만 넣어둔거고요~

    freetds 를 활용하시면 간단히 해결됩니다.
    -- 호스팅 이용하시는 분은 모.. -_-  노가다 하셔야합니다. ;;


    추가 Tip... 제대로 옮겨왔는지.. 테이블별 레코드수가 맞나 비교하기 위해..
    MSSQL 의 sysindexes 와 sysobjects 를 활용하여 DB의 모든 테이블 별 레코드수를 가져와서 비교해 보시면 편하겠죠~

    select o.name as TABLE_NAME, i.rows as ROW_COUNT_ALL
        from sysindexes i INNER JOIN sysobjects o ON i.id = o.id
        where o.xtype = 'U' //U-테이블만..
        and i.indid < 2
        and o.name <> 'sysdiagrams'
        order by o.name


    즐프 하세요
    2010/07/14 08:53 2010/07/14 08:53
    이 글의 관련글

    Trackback Address : http://www.1go.co.kr/blog/trackback/3886

    [로그인][오픈아이디란?]
    안주꺼리 2010/07/12 17:32
  • 글라스우드 - 난연, 무독성, 방부, 방충, 치수안정성, 강도, 내구성 등 탁월한 성능을 발휘하도록 만든 불용성 목재
  • CSS(CLASS)를 사용한 SHOW , HIDE 방법 [NEW]

    작성자

    예제모양

    div ID : div_1
    li ID : li_hide_11 , li_hide_12

    • 이것은 좋은것이다.
    • 공대여자는?
      • "공대여자가 이쁘다."는건 진리이다.
    • 공대여자 홈페이지는

    JS로만 처리할 경우

    div ID : div_2
    li ID : li_hide_21 , li_hide_22

    • 이것은 좋은것이다.
    • 공대여자는?
      • "공대여자가 이쁘다."는건 진리이다.
    • 공대여자 홈페이지는
    스크립트

    CSS의 class를 추가해서 처리할 경우

    div ID : div_3
    li ID : li_hide_31 , li_hide_32

    • 이것은 좋은것이다.
    • 공대여자는?
      • "공대여자가 이쁘다."는건 진리이다.
    • 공대여자 홈페이지는

    스크립트
    CSS


    설명

    1. JS로만 할 경우
      1. 숨길태그를 모두 알고있어야된다.(ID를 알거나 DOM으로 찾아가거서)
      2. 그후 숨길태그 하나마다의 style.display를 none이나 block으로 변경
    2. CSS의 class를 추가해서 할 경우
      1. 미리 설정
        1. class를 미리 정의해둔다.
        2. 숨길태그는 dOff 등으로 class를 지정해둔다.
        3. 부모태그는 on(숨길태그 보임) , off(숨길태그 안보임) 중 하나로 class를 지정(안해도.. 뭐뭐..)
      2. 숨길태그들을 포함하는 부모태그(ID나 form등으로)를 알고있어야한다.
      3. 부모태그의 class를 on이나, off로 변경

    결론?

    • 같은 구조의 디자인이 반복될 때 CLASS 사용하면 좋다.

    잡담

    • 대상을 지정하는 법은 document.getElementById 같이 id로 접근하는 법이 있지만
      form을 사용해서 <input type="button"> 에서 onclick 시 fn(this.form) 처럼 form을 지정해버리는 방법도 있고
      this.parentNode 처럼 상위노드를 찾아가는 방법도 있다.
      • 즉, 여러 방법이 있으니... 하나의 방법을 고집할 필요는 없다.
        개인적으로 form으로 감싸는 방법을 추천.
    2010/07/12 17:32 2010/07/12 17:32
    이 글의 관련글

    Trackback Address : http://www.1go.co.kr/blog/trackback/3870

    [로그인][오픈아이디란?]
    안주꺼리 2010/07/09 10:01
  • 글라스우드 - 난연, 무독성, 방부, 방충, 치수안정성, 강도, 내구성 등 탁월한 성능을 발휘하도록 만든 불용성 목재
  • 프록시 서버 검출 하는게 필요 해서 여기저기 자료를 찾아 보았는데

    양키 홈피에서 괜찮은 방법을 찾아서 올립니다. 

    기본적으로 프록시 서버는 

    1. Transparent  : 헤더의 X-Forwaded-For 코드로 확인 가능

    2. anonymous : 헤더의 Via 코드로 확인가능

    3. High anonymous : 보통 헤더와 동일 하기 때문에 검출 불가능 (양키 홈피에서 해결 방안을 제시함. )

    로 나누어 집니다.  그래서 일반적으로는 1,2번의 경우만 검출이 가능 합니다.

    아래가 해당 1,2번의 경우 프록시 서버사용의 검출 코드입니다.

    $proxy_headers = array

    'HTTP_VIA', 
    'HTTP_X_FORWARDED_FOR', 
    'HTTP_FORWARDED_FOR', 
    'HTTP_X_FORWARDED', 
    'HTTP_FORWARDED', 
    'HTTP_CLIENT_IP', 
    'HTTP_FORWARDED_FOR_IP', 
    'VIA', 
    'X_FORWARDED_FOR', 
    'FORWARDED_FOR', 
    'X_FORWARDED', 
    'FORWARDED', 
    'CLIENT_IP', 
    'FORWARDED_FOR_IP', 
    'HTTP_PROXY_CONNECTION'
    );

    foreach($proxy_headers as $x)
    {
        if (isset($_SERVER[$x])) die("You are using a proxy!");
    }

    여기서 3번의 경우가 검출이 되지 않기 때문에 양키 홈피에서는 프록시 서버에서 자주 사

    용하는 포트를 확인하는 방법으로 프록시 서버를 인식 합니다.  코드는 다음과 같습니다.

    $ports = array(8080,80,81,1080,6588,8000,3128,553,554,4480);
    foreach($ports as $port) {
        if (@fsockopen($_SERVER['REMOTE_ADDR'], $port, $errno, $errstr, 5)) {
            die("You are using a proxy!");
        }
    }

    실제 사용 결과 상당한 수준의 프록시 서버 체크가 가능했습니다. 

    실무에서 사용 할수 있을지 어떨지는 잘 모르겠지만 혹시나 필요 하신 분이 있을까 싶어서 올립니다.


    출처 : http://w-shadow.com/blog/2007/11/23/det ··· proxy%2F
    2010/07/09 10:01 2010/07/09 10:01
    이 글의 관련글

    Trackback Address : http://www.1go.co.kr/blog/trackback/3846

    [로그인][오픈아이디란?]
    안주꺼리 2010/07/07 14:55
  • 글라스우드 - 난연, 무독성, 방부, 방충, 치수안정성, 강도, 내구성 등 탁월한 성능을 발휘하도록 만든 불용성 목재
  • MySql에서의 한글사용에 대한 질문이 많고 종래의 EUC-KR로 만들어진 홈페이지를 첨단 만국어를 표기할 수 있는 UTF-8 사용에 대해 요약하였습니다.
    ==================================================================================
    종래에는 홈페이지가 자국인들만 이용할 것을 예상하고 제작하므로써 외국인 즉, 비한글 사용자들에 대한 서비스를 미쳐 염두에 두지 못하므로써 한글이 ?????$%^&( 처럼 깨져 보이는 무지함을 보였던 것이 사실입니다.

    이제는 홈페이지 제작도 유니코드(UTF-8) 인코딩 방식이 세계적 추세이며 이러한 추세에 맞추어 MySql도 기본언어를 utf8(UTF-8 인코딩) 방식으로 변경하였으므로, 홈페이지를 종래 euc-kr 등 한글로만 표기하던 방식도 UTF-8 인코딩 방식으로 업데이트해야 할 때 입니다. UTF-8 인코딩 방식은 한국어, 일어, 중국어, 태국어, 아랍어 등 만국어 표기가 가능한 방식입니다.

    APM에서 UTF-8을 구현하려면 꽤 많은 부분을 수정해야 합니다 .
    다음은 APM에서 UTF-8 구현 방법과 소스코드를 첨부합니다.
    적용 환경
    ----------------
    OS : WinXP SP2
    Apache : httpd-2.0.52-3
    PHP : php-5.0.3
    MySQL : mysql-4.1.11
    ----------------
    * 아래 내용 말고도 OS와 브라우저가 지원해 주어야 하지만, OS는 Win98 부터 지원하고 있으며 많이 쓰는 익스플로러도 역시 지원하고 있으니 손쉽게 설정을 변환할 수 있습니다.

    1. apache 환경파일 편집 (httpd.conf)
    2. php 환경파일 편집 (php.ini)
    3. mysql 환경파일 편집 (my.cnf)
    4. apache, mysql 서비스 재시작
    5. mysql에서 캐릭터셋 확인 및 디비생성
    6. php 소스코드에 @mysql_query("set names utf8"); 함수 추가
    7. php 소스에 한글문자열이 있으면 파일저장할때 UTF-8 파일형식으로 저장
    8. 웹브라우저의 보기-인코딩-UTF-8로 선택
    9. 아웃룩 익스프레스 : 도구->옵션->읽기->글꼴->인코딩:유니코드(UTF-8)->
    기본설정 클릭. 국가별 설정->"모든 받는 메시지에 기본 인코딩 사용"에는 체크를 해제.
    (여기에 체크하면 EUC-KR 이나 다른 언어로 작성된 메일은 깨지게 됨)
    * 추가 : 6번 php소스 페이지에 @mysql_query("set names utf8"); 함수를 추가하는 문제는
    먼저 header.php파일에 추가하면 대부분 작동하며, 예외적으로 작동이 안되는
    파일이 간혹 있으므로 천천히 점검해서 필요한 페이지에 추가해 주면 됩니다.
    * htmlentities() 버그 :
    $xsitename = htmlentities($xsitename, ENT_QUOTES); 와 같은 사용례에서는 utf8로
    입력되지 않는 경우가 있는데, php 버그라고 하며 펫치가 나와 있답니다.
    추가 : htmlentities() 때문에 한글이 깨지면 htmlspecialchars로 대치해도 됩니다.

    1. apache/conf/httpd.conf 에서 캐릭터셋 수정
    /*------------
    AddDefaultCharset UTF-8

    2. etc/php.ini 에서 캐릭터셋 수정
    /*------------
    ;default_charset = "iso-8859-1"
    default_charset = "utf-8"
    * 위와 같이 지정해야 한다고 주장하는 사람도 있으나 필자의 경우 default_charset = "utf-8" 로 지정하지 않고 초기 설정상태로 두어도 무방하였음.

    3. etc/my.cnf (또는 my.ini) 에서 캐릭터셋 수정
    /*------------
    [client]
    #password = your_password
    default-character-set=utf8

    [mysqld]
    init_connect=SET collation_connection = utf8_general_ci
    init_connect=SET NAMES utf8
    default-character-set=utf8
    character-set-server=utf8
    collation-server=utf8_general_ci

    [mysql]
    default-character-set=utf8

    4. 환경변수를 모두 수정후 apache 및 mysql 서비스 재시작
    /*------------

    5. mysql에서 캐릭터셋 확인
    /*------------
    # mysql
    Welcome to the MySQL monitor. Commands end with ; or \g.
    Your MySQL connection id is 247 to server version: 4.1.10a

    Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

    mysql> use test
    Database changed
    mysql> show variables like 'c%';
    +---------+-----------+
    | Variable_name | Value |
    +---------+-----------+
    | character_set_client | utf8 |
    | character_set_connection | utf8 |
    | character_set_database | utf8 |
    | character_set_results | utf8 |
    | character_set_server | utf8 |
    | character_set_system | utf8 |
    | character_sets_dir | /usr/share/mysql/charsets/ |
    | collation_connection | utf8_general_ci |
    | collation_database | utf8_general_ci |
    | collation_server | utf8_general_ci |
    | concurrent_insert | ON |
    | connect_timeout | 5 |
    +---------+-----------+
    12 rows in set (0.00 sec)

    * MySql에서 데이터베이스 생성
    mysql>CREATE DATABASE 디비명 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;

    * 아래 첨부파일은 기작성된 디비의 테이블과 글자셋을 변경하는 스크립트입니다.
    2010/07/07 14:55 2010/07/07 14:55
    이 글의 관련글

    Trackback Address : http://www.1go.co.kr/blog/trackback/3836

    [로그인][오픈아이디란?]
    안주꺼리 2010/07/04 19:46
  • 글라스우드 - 난연, 무독성, 방부, 방충, 치수안정성, 강도, 내구성 등 탁월한 성능을 발휘하도록 만든 불용성 목재
  • php.net에 공개소스 가저다 조금 손본거예요.

    최근 다운소스중에서 쓸만하네요.





    -- vDown.php ----------------------------------

    function fDown($file,$name,$downview,$speed,$limit)// 경로, 원파일명, 다운 1/보임0, 다운속도, 속도제한여부

    {

        //do something on download abort/finish

        //register_shutdown_function( 'function_name'  );

        if(!file_exists($file))

            die('File not exist!');

        $size = filesize($file);

        $name = rawurldecode($name);



        if (ereg('Opera(/| )([0-9].[0-9]{1,2})', $_SERVER['HTTP_USER_AGENT']))

            $UserBrowser = "Opera";

        elseif (ereg('MSIE ([0-9].[0-9]{1,2})', $_SERVER['HTTP_USER_AGENT']))

            $UserBrowser = "IE";

        else

            $UserBrowser = '';



        $downview = ($downview) ? "attachment" : "inline";



        /// important for download im most browser

        $mime_type = ($UserBrowser == 'IE' || $UserBrowser == 'Opera')? 'application/octetstream' : 'application/octet-stream';

        @ob_end_clean(); /// decrease cpu usage extreme

        Header('Content-Type: ' . $mime_type);

        Header('Content-Disposition: '.$downview.'; filename="'.$name.'"');

        Header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");

        Header('Accept-Ranges: bytes');

        Header("Cache-control: private");

        Header('Pragma: private');



        /////  multipart-download and resume-download

        if(isset($_SERVER['HTTP_RANGE']))

        {

            list($a, $range) = explode("=",$_SERVER['HTTP_RANGE']);

            str_replace($range, "-", $range);

            $size2 = $size-1;

            $new_length = $size-$range;

            Header("HTTP/1.1 206 Partial Content");

            Header("Content-Length: $new_length");

            Header("Content-Range: bytes $range$size2/$size");

        } else {

            $size2=$size-1;

            Header("Content-Length: ".$size);

        }

        $chunksize = 1*(1024*$speed);

        $bytes_send = 0;

        if ($file = fopen($file, 'rb'))

        {

            if(isset($_SERVER['HTTP_RANGE']))

                fseek($file, $range);

            while(!feof($file) and (connection_status()==0))

            {

                $buffer = fread($file, $chunksize);

                print($buffer);//echo($buffer); // is also possible

                flush();

                $bytes_send += strlen($buffer);

                if($limit) sleep(1); // 다운로드 속도제한

            }

            fclose($file);

        } else

            die('Error can not open file!!');

        if(isset($new_length))

            $size = $new_length;

        die('Error can not open file!!');

        Header("Connection: close");

    }





    if(다운가능권한이있다면){



        // 파일정보 가져오기

        $sql = "select * from 파일정보DB명 where no='$_GET[fNo]";

        $fNa = mysql_fetch_object(mysql_query($sql));

       

                    fDown($fNa->fName, $fNa->oName, $_GET[v], '200', '1'); //함수호출 200k 바이트로 속도제한을 사용해서 fName를 oName파일명으로 다운로드합니다.

           



    } else { // 권한이있다면 끝

       

        GoBack('You Level Low !!!');



    } // 권한검사끝

    mysql_close();

    ?>



    <a href='vDown.php?fNo=2&v=1'>다운로드</a>

    <a href='vDown.php?fNo=2&v=2'>보기</a>




    2010/07/04 19:46 2010/07/04 19:46
    이 글의 관련글

    Trackback Address : http://www.1go.co.kr/blog/trackback/3815

    1. 파일 다운로드 함수(멀티 이어받기/속도제한)

      올렉동영상UCC뉴스 2010/07/06 11:07

      php.net에 공개소스 가저다 조금 손본거예요. 최근 다운소스중에서 쓸만하네요.-- vDown.php ----------------------------------<?php function fDown($file,$name,$downview,$speed,$limit)// 경로, 원파일명, 다운 1/보임0, 다운속도, 속도제한여부{ //do something on download abort/finish //register_shutdown_functi...

    [로그인][오픈아이디란?]
    안주꺼리 2010/04/29 10:10
  • 글라스우드 - 난연, 무독성, 방부, 방충, 치수안정성, 강도, 내구성 등 탁월한 성능을 발휘하도록 만든 불용성 목재
  • 문자열에서 필요한 부분만 취하는 방법 관련하여
    문자열과 정규식 등 다양한 방법을 이용해봤습니다.


    비록 단순한 내용이지만 문자열 처리와 관련하여
    아래의 코드들이 여러모로 보탬이 될까 싶어 등록합니다.
    다른 방법 남겨주시면 감사하겠습니다. ^^)/


    $date = '2010년04월20일'; // 형태는 4년2월2일

    이 값에서 숫자 부분인 '20100420'만 뽑는 방법입니다.



    먼저 문자열(배열 관련 함수를 많이 사용하지만) 처리 방법입니다.


    ▶ 문자열 처리 #1

    고정 길이기 때문에 substr() 함수를 이용합니다.

    ────────────────────────────────────────
    $date = substr($date,0,4).substr($date,6,2).substr($date,10,2);
    ────────────────────────────────────────

    substr() : http://php.net/manual/kr/function.substr.php

    참고로 .은 문자열 결합 연산자입니다.
    String Operators : http://php.net/manual/kr/language.operators.string.php



    ▶ 문자열 처리 #2

    str_replace() 함수를 이용해 년, 월, 일 문자를 제거합니다.

    ────────────────────────────────────────
    $date = str_replace('년','',$date); // 201004월20일
    $date = str_replace('월','',$date); // 20100420일
    $date = str_replace('일','',$date); // 20100420
    ────────────────────────────────────────

    str_replace() : http://php.net/manual/kr/function.str-replace.php

    참고로 해석이 필요없는 문자열 값은 '(Single Quote)로 감싸주세요.
    문자열 관련 : http://php.net/manual/en/language.types.string.php


    ▶ 문자열 처리 #3

    strtr() 함수를 이용하면 #2 과정을 한 번에 처리할 수 있습니다.

    ────────────────────────────────────────
    $remove['년'] = '';
    $remove['월'] = '';
    $remove['일'] = '';

    // 또는

    $remove = array('년'=>'','월'=>'','일'=>'');

    // 둘 중 편한 형태로 미리 연관 배열을 할당합니다.

    $date = strtr($date,$remove);

    // 물론 변수에 담지 않고 바로 이용도 가능합니다.

    $date = strtr($date,array('년'=>'','월'=>'','일'=>''));
    ────────────────────────────────────────

    strtr() : http://php.net/manual/en/function.strtr.php
    연관 배열 : http://php.net/manual/kr/language.types.array.php


    ▶ 문자열 처리 #4

    explode() 함수를 이용해 년, 월, 일을 잘라줍니다.

    ────────────────────────────────────────
    $a = explode('년',$date); // [0] => 2010 [1] => 04월20일
    $b = explode('월',$a[1]); // [0] => 04 [1] => 20일
    $c = explode('일',$b[1]); // [0] => 20 [1] =>
    $date = $a[0].$b[0].$c[0];
    ────────────────────────────────────────

    reset() 함수로 배열의 첫 번째 값을 쉽게 가져올 수 있습니다.
    array_shift() 함수로 배열의 첫 번째 값을 뺄 수 있습니다.

    explode() : http://php.net/manual/kr/function.explode.php
    reset() : http://php.net/manual/kr/function.reset.php
    array_shift() : http://php.net/manual/kr/function.array-shift.php


    ▶ 문자열 처리 #5

    list() 함수를 이용하면 #4 변수 사용이 좀 더 간편해집니다.

    ────────────────────────────────────────
    list($y,$date) = explode('년',$date); // $y=2010, $date=04월20일
    list($m,$d) = explode('월',$date); // $m=04, $d=20일
    list($d) = explode('일',$d); // $d=20
    $date = $y.$m.$d;
    ────────────────────────────────────────

    list() : http://php.net/manual/kr/function.list.php


    ▶ 문자열 처리 #6

    explode()와 함께하는 implode() 함수를 이용해보겠습니다.

    ────────────────────────────────────────
    $date = implode('',explode('년',$date));
    $date = implode('',explode('월',$date));
    $date = implode('',explode('일',$date));
    ────────────────────────────────────────

    implode() : http://php.net/manual/kr/function.implode.php


    ▶ 문자열 처리 #7

    sscanf() 함수를 이용하면 형식에 맞게 값을 뽑을 수 있습니다.
    다만, 앞에 0이 붙었으면 0을 제거해주기 때문에 조정이 필요합니다.

    ────────────────────────────────────────
    $temp = sscanf($date,'%4d년%2d월%2d일'); // [0] => 2010 [1] => 4 [2] => 20
    if ( $temp[1]<10 ) $temp[1] = '0'.$temp[1]; // 4 => 04
    if ( $temp[2]<10 ) $temp[2] = '0'.$temp[2];
    $date = implode('',$temp); // $date = $temp[0].$temp[1].$temp[2];
    ────────────────────────────────────────

    sscanf() : http://php.net/manual/kr/function.sscanf.php


    ▶ 문자열 처리 #8

    #7의 코드에 그 위에서 언급한 list() 함수를 이용해볼까요?

    ────────────────────────────────────────
    list($y,$m,$d) = sscanf($date,'%4d년%2d월%2d일'); // $y=2010, $m=4, $d=20
    if ( $m<10 ) $m = '0'.$m;
    if ( $d<10 ) $d = '0'.$d;
    $date = $y.$m.$d;
    ────────────────────────────────────────

    참고로 each() 함수를 살펴보세요. list() 함수와 궁합이 좋습니다.
    each() : http://php.net/manual/kr/function.each.php


    ▶ 문자열 처리 #9

    sscanf()에서 곧바로 변수 할당도 가능합니다.
    이번에는 sprintf() 함수로 형식에 맞는 문자열을 만들어보겠습니다.

    ────────────────────────────────────────
    sscanf($date,'%4d년%2d월%2d일',$y,$m,$d); // $y=2010, $m=4, $d=20
    $date = sprintf('%04d%02d%02d',$y,$m,$d);
    ────────────────────────────────────────

    sprintf() : http://php.net/manual/kr/function.sprintf.php


    ▶ 문자열 처리 #10

    strpos() 함수를 이용하면 지정한 문자(열)의 위치를 구할 수 있습니다.

    ────────────────────────────────────────
    $py = strpos($date,'년'); // 4
    $pm = strpos($date,'월'); // 8
    $pd = strpos($date,'일'); // 12
    $date = substr($date,0,$py).substr($date,$py+2,2).substr($date,$pm+2,2);
    ────────────────────────────────────────

    strpos() : http://php.net/manual/kr/function.strpos.php


    ▶ 문자열 처리 #11

    이번에는 고전적인 방법을 이용해보겠습니다.
    문자열의 길이만큼 반복하며 1바이트씩 읽어 숫자일 때 붙여주는 것이죠.
    먼저 풀어쓴 코드부터 보시죠.

    ────────────────────────────────────────
    $original = $date; // $original에 기존 $date값을 할당
    $len = strlen($date); // 문자열 길이 구해주고
    $date = ''; // 결과값을 이곳에 담기 위해 빈 문자열로
    for ($i=0;$i<$len;$i++) // 길이만큼 반복
    {
        if ( is_numeric($original[$i]) ) $date.= $original[$i]; // 숫자인 경우 붙임
    }
    ────────────────────────────────────────

    for() : http://php.net/manual/kr/control-structures.for.php
    strlen() : http://php.net/manual/kr/function.strlen.php
    is_numeric() : http://php.net/manual/kr/function.is-numeric.php
    ctype_digit() : http://php.net/manual/kr/function.ctype-digit.php

    편의상 is_numeric() 함수를 이용했습니다.
    그리고 위에서 보다시피 '2010년04월20일'은 문자열 값이지만
    []를 이용해 배열처럼 접근할 수 있습니다.


    ▶ 문자열 처리 #12

    #11보다 더 고전적인 방법입니다. 아스키 값을 이용합니다.

    ────────────────────────────────────────
    $original = $date; // $original에 기존 $date값을 할당
    $len = strlen($date); // 문자열 길이 구해주고
    $date = ''; // 결과값을 이곳에 담기 위해 빈 문자열로
    for ($i=0;$i<$len;$i++) // 길이만큼 반복
    {
        $c = $original[$i]; // 1바이트 문자
        $asc = ord($c); // 아스키 코드
        if ( $asc<48 || $asc>57 ) continue; // 숫자 범위 아니면 Skip
        $date.= $c;
    }
    ────────────────────────────────────────

    숫자 범위가 아니면 위와 같은 조건이면 됩니다.
    숫자 범위로 조건을 바꾼다면? ( $asc>47 && $asc<58 )입니다.

    참고로 <= 비교보다 < 비교가 빠릅니다.
    그래서 ( $asc>=48 && $asc<=57 )로 하기보다 위 조건을 권장합니다.
    누누이 강조하는 부분이지만 쓰기 나름이니까 편한 대로 쓰면 됩니다.

    또는 어차피 숫자 외의 문자열이라봐야 년, 월, 일이니
    아스키 값이 127 이상인 경우를 걸러주면 됩니다.

    ord() : http://php.net/manual/kr/function.ord.php
    ASCII Table : http://www.asciitable.com/


    ▶ 문자열 처리 #13

    #11, #12의 for()문을 줄인 형태입니다.

    ────────────────────────────────────────
    for($i=0,$o=$date,$date='',$l=strlen($o);$i<$l;$i++)if(is_numeric($o[$i]))$date.=$o[$i];
    ────────────────────────────────────────


    ▶ 문자열 처리 #14

    #13을 아예 for()문으로 끝내는 것도 가능합니다.

    ────────────────────────────────────────
    for ($i=0,$l=strlen($o=$date),$date='';$i<$len;$i++,$date.=is_numeric($o[$i-1])?$o[$i-1]:'');
    ────────────────────────────────────────

    빠질 뻔 했는데 값의 할당은 오른쪽부터 왼쪽으로 진행됩니다.
    $l=strlen($o=$date)
    $o에 $date가 할당되고, $o의 길이가 $l에 할당됩니다.
    할당 연산자 : http://php.net/manual/kr/language.opera ··· ment.php
    연산자 우선권 : http://php.net/manual/kr/language.opera ··· ence.php


    ▶ 문자열 처리 #15

    "키=값" 형태로 가공해 parse_str() 함수를 이용하는 방법입니다.

    ────────────────────────────────────────
    $date = 'y='.substr($date,0,-2); // y=2010년04월20
    $date = str_replace('년','&m=',$date); // y=2010&m=04월20
    $date = str_replace('월','&d=',$date); // y=2010&m=04&d=20
    parse_str($date);
    $date = $y.$m.$d;

    ────────────────────────────────────────

    parse_str() 함수를 보면, extract() 함수가 떠오르죠.

    parse_str() : http://php.net/manual/kr/function.parse-str.php
    extract() : http://php.net/manual/kr/function.extract.php

    두 번째 인자를 주면 그 변수에 값을 받게 됩니다.

    ‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥
    // 위 3줄 동일
    parse_str($date,$t); // 'y'=>'2010', 'm'=>'04', 'd'=>'20'
    $date = implode('',$t); // $date = $t['y'].$t['m'].$t['d'];
    ‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥


    ▶ 문자열 처리 #16

    #11 ~ #14의 코드와 비슷합니다.
    []를 이용해 문자열도 배열 형태로 접근이 가능하다고 했죠?
    이번에는 문자열을 정말 배열로 만들어 처리해보겠습니다.
    그리고 똑같은 코드로 하면 재미없으니 다른 코드를 부르겠습니다.

    ────────────────────────────────────────
    $temp = str_split($date);
    $date = '';
    foreach ( $temp as $char )
    {
        if ( ord($char)<128 ) $date.= $char;
    }
    ────────────────────────────────────────

    1바이트로 나눠 배열 끝까지 반복, 아스키 값 비교로 결과값을 구합니다.
    foreach()도 참 유용한 제어 구조 중 하나입니다. 배열과 찰떡 호흡!

    str_split() : http://php.net/manual/kr/function.str-split.php
    foreach() : http://php.net/manual/kr/control-structures.foreach.php


    ‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥
    $t=str_split($date);$date='';
    foreach($t as $c)if(ord($c)<128)$date.=$c;
    ‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥


    ▶ 문자열 처리 #17

    substr_replace()를 깜빡했군요. str_replace()와 비교해보는 재미를···.

    ────────────────────────────────────────
    $date = substr_replace($date,'',4,2); // 201004월20일
    $date = substr_replace($date,'',6,2); // 20100420일
    $date = substr_replace($date,'',8,2); // 20100420
    ────────────────────────────────────────

    substr_replace() : http://php.net/manual/en/function.substr-replace.php



    정규식으로 처리하는 방법 역시 다양합니다.


    ■ 정규식 처리 #1

    제일 간단한 방법은 숫자 외의 문자를 제거하는 것입니다.

    ────────────────────────────────────────
    $date = preg_replace('/\D/','',$date);
    ────────────────────────────────────────

    10진 숫자가 아닌 임의의 문자(\D)를 ''로 치환해주는 방법이죠.

    정규 표현식 상세 : http://php.net/manual/kr/regexp.reference.php
    정규 표현식 : http://php.net/manual/en/reference.pcre ··· ntax.php

    임의의 10진 숫자는 \d로 표현합니다. 또는 [0-9]로 표현하죠.
    여기에 부정 클래스를 사용하면 반대가 됩니다.

    ‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥
    $date = preg_replace('/[^0-9]/','',$date);
    $date = preg_replace('/[^\d]/','',$date);
    ‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥

    preg_replace() : http://php.net/manual/kr/function.preg-replace.php

    참고로 ereg_replace(), eregi_replace() 등 POSIX Regex 관련 함수들은
    PHP 5.3 버전부터 중지됩니다.
    POSIX Regex 관련 함수 : http://php.net/manual/kr/ref.regex.php

    그러니 어서 펄 호환 정규식으로 갈아타시길···.
    Regular Expressions (Perl-Compatible) : http://php.net/manual/kr/book.pcre.php


    ■ 정규식 처리 #2

    숫자만 뽑아 묶어주는 방법입니다.

    ────────────────────────────────────────
    preg_match_all('/\d/',$date,$matches);
    $date = implode('',$matches[0]);
    ────────────────────────────────────────

    위와 같이 실행했을 때 $matches의 값입니다.
    문자열 처리 과정에서 언급한 implode() 함수로 깔끔하게 묶어주면 됩니다.

    ‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥
    Array
    (
        [0] => Array
            (
                [0] => 2
                [1] => 0
                [2] => 1
                [3] => 0
                [4] => 0
                [5] => 4
                [6] => 2
                [7] => 0
            )
    )
    ‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥

    preg_match_all() : http://php.net/manual/kr/function.preg-match-all.php


    ■ 정규식 처리 #3

    preg_split() 함수로 대놓고 년, 월, 일로 잘라줘도 됩니다.

    ────────────────────────────────────────
    list($y,$m,$d) = preg_split('/년|월|일/',$date);
    $date = $y.$m.$d;
    ────────────────────────────────────────

    preg_split() : http://php.net/manual/kr/function.preg-split.php

    차근차근 읽어본 경우라면 위 두 줄의 코드를 한 줄로 바꿀 수 있겠죠?

    ‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥
    $date = implode('',preg_split('/년|월|일/',$date));
    ‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥


    ■ 정규식 처리 #4

    #1의 코드와 기본은 같고 메타 문자만 다릅니다.

    ────────────────────────────────────────
    $date = preg_replace('/\W/','',$date);
    ────────────────────────────────────────

    어떠한 문자나 숫자, _가 \w며, \W는 그 반대입니다.
    특성이 있지만, 년, 월, 일 정도야···. ^^);;;


    ■ 정규식 처리 #5

    preg_grep()의 활용 예를 위해 하나 더 추가합니다.
    str_split() 함수와 마찬가지로 잘라주고, 숫자 부분만 가져다 묶어줍니다.

    ────────────────────────────────────────
    $split = preg_split('//',$date,-1,PREG_SPLIT_NO_EMPTY);
    $date = implode('',preg_grep('/\d/',$split));
    ────────────────────────────────────────

    preg_grep() : http://php.net/manual/kr/function.preg-grep.php

    ‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥
    $date = implode('',preg_grep('/\d/',preg_split('/()/',$date,-1,PREG_SPLIT_NO_EMPTY)));
    ‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥


    ■ 정규식 처리 #6

    #2에서 preg_match_all()을 사용했죠? 이번에는 preg_match() 사용입니다.

    ────────────────────────────────────────
    preg_match('/(\d+)년(\d+)월(\d+)일/',$date,$match);
    $date = implode('',array_slice($match,1));
    ────────────────────────────────────────

    $match의 값은 아래와 같습니다.

    ‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥
    Array
    (
        [0] => 2010년04월20일
        [1] => 2010
        [2] => 04
        [3] => 20
    )
    ‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥

    여기서 array_slice() 함수를 이용해 두 번째 배열부터 가져와 묶어줍니다.
    문자열의 substr() 함수와 사용 방법이 같습니다. 대상만 배열이죠.

    preg_match() : http://php.net/manual/kr/function.preg-match.php
    array_slice() : http://php.net/manual/kr/function.array-slice.php



    ■ 정규식 처리 #7

    응용 예입니다.

    ────────────────────────────────────────
    preg_match('/(\d+)(\W.)(\d+)(\W.)(\d+)(\W.)/',$date,$matches);
    $date = $matches[1].$matches[3].$matches[5];
    ────────────────────────────────────────

    $matches 값은 아래와 같습니다.

    ‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥
    Array
    (
        [0] => 2010년04월20일
        [1] => 2010
        [2] => 년
        [3] => 04
        [4] => 월
        [5] => 20
        [6] => 일
    )
    ‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥



    ▣ 날짜 함수 이용

    문자열 처리 응용, strtotime() 함수와 date() 함수가 등장합니다.
    년, 월, 일을 제거하면 그것으로 끝이지만 응용 차원에서 추가했습니다.
    참. 꼭 -으로 바꿀 필요는 없습니다.

    ────────────────────────────────────────
    $date = str_replace('년','-',$date); // 2010-04월20일
    $date = str_replace('월','-',$date); // 2010-04-20일
    $date = str_replace('일','',$date); // 2010-04-20
    $date = date('Ymd',strtotime($date));
    ────────────────────────────────────────

    strtotime() : http://php.net/manual/en/function.strtotime.php
    date() : http://php.net/manual/kr/function.date.php

    한 줄로 줄이려면? 문자열 처리 #3에서 언급한 strtr()을 사용하면 됩니다.

    ‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥
    echo date('Ymd',strtotime(strtr($date,array('년'=>'/','월'=>'/','일'=>''))));
    ‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥



    다양한 표현이 가능하지만 이쯤에서 마치도록 하겠습니다.
    이렇게 나열하고 보니 엎어치나 메치나 같죠?


    * 일단 제가 아는 방법은 대부분 적은 것 같습니다.
     다른 방법들 있으면 좀 알려주세요. ^^);;;

    * Multibyte String 함수는 생략했습니다.
     http://php.net/manual/en/function.mb-substr.php

    * 어디까지나 쓰기 나름임을 강조하며, 활용은 본인 몫입니다. D.I.Y!

    * 년, 월, 일은 EUC-KR 기반 2바이트, UTF-8 기준 3바이트입니다.
     본문에서는 EUC-KR 기준입니다. 유념!
     예를 들어 월값 구하는 부분에서 substr($date,6,2)는
     연도 4자리 + '년' 3바이트해서 substr($date,7,2)로 잡아줘야 합니다.
    2010/04/29 10:10 2010/04/29 10:10
    이 글의 관련글

    Trackback Address : http://www.1go.co.kr/blog/trackback/3756

    [로그인][오픈아이디란?]
    안주꺼리 2010/04/15 17:53
  • 글라스우드 - 난연, 무독성, 방부, 방충, 치수안정성, 강도, 내구성 등 탁월한 성능을 발휘하도록 만든 불용성 목재
  • 다시 올립니다;; ^^;;;
    모든 통신기종에서 테스트 해보지는 않았습니다.
    하지만 될것입니다-_-; 칼라폰을 제외하고는;
    mnuri(www.mnuri.co.kr (새 창으로 열기))라는 모바일홈페이지 공간을 주는곳에 공개된 ASP소스를 변경한것입니다.

    <?
    $agent=getenv("HTTP_USER_AGENT");
    $subno=getenv("HTTP_X_UP_SUBNO");

        if(eregi("SKT",$agent)) // 011 휴대폰인 경우 [WML]
            Header("Location:index.wml.php");

        elseif(eregi("STI",$agent)) // SK-신세기통신(017)의 휴대폰인 경우 [WML]
            Header("Location:index.wml.php");

        elseif(eregi("CellPhone",$agent)) // 016,018 휴대폰인 경우 [mHTML]
            Header("Location:index.mhtml.php");

        elseif(eregi("itouch",$subno)||eregi("ezweb",$subno)) // 017,019 휴대폰인 경우 [HDML]
            Header("Location:index.hdml.php");

        elseif(eregi("UP.Browser/3.1",$agent)) // hdml용 UP브라우저3.1 시뮬레이터인 경우 [HDML]
            Header("Location:index.hdml.php");

        elseif(eregi("UP.Browser/3.2",$agent)) // hdml용 UP브라우저3.2 시뮬레이터인 경우 [HDML]
            Header("Location:index.hdml.php");

        elseif(eregi("UP.Browser/4.0",$agent)) // UP브라우저4.0 시뮬레이터인 경우 [WML]
            Header("Location:index.wml.php");

        elseif(eregi("UP.Browser/4.1",$agent)) // UP브라우저4.1인 017/019 휴대폰인 경우 [WML]
            Header("Location:index.wml.php");

        elseif(eregi("UP.Browser/4.1",$agent)&&eregi($agent,"UPG")) // WML용 UP브라우저4.1 시뮬레이터인 경우 [WML]
            Header("Location:index.wml.php");

        elseif(eregi("Mozilla",$agent)) // 일반브라우저인경우
            Header("Location:Browser.html");
    ?>

    2010/04/15 17:53 2010/04/15 17:53
    이 글의 관련글

    Trackback Address : http://www.1go.co.kr/blog/trackback/3715

    [로그인][오픈아이디란?]
    안주꺼리 2010/04/15 17:08
  • 글라스우드 - 난연, 무독성, 방부, 방충, 치수안정성, 강도, 내구성 등 탁월한 성능을 발휘하도록 만든 불용성 목재
  • <?php
    /******************************************************************************
    *    프로그램명    : 갈쿠리
    *    버젼                : 1.01
    *    변경일            : 2006-09-14
    *    작성자            : 강용석
    *    메일                : zzr600@hanmail.net
    *    용도                : 텍스트 파싱
    ******************************************************************************/

    class GalKuRi {
        // public
        var $response_header        = '';                // 응답헤더 저장
        var $contents                    = '';                // 페이지 전체 내용 저장
        var $parse_value                = array();        // 결과가 저장될 배열

        // private
        var $_goods_no                = 0;                // 결과배열에 저장할때 쓰일 상품 번호
        var $_offset                        = 0;                // 검색 시작 번지
        var $_page_no                    = 0;                // 페이지 별로 읽을 경우 페이지 번호 저장변수
        var $_page_var                    = '';                // 페이지 별로 읽을 경우 페이지 변수명을 저장하는 변수
        var $_parse_pattern            = array();        // 읽어들일 문자 패턴 2차원배열
        var $_process_func            = '';                // 페이지 별로 처리할때 결과를 처리할 외부함수
        var $_roop                        = 1;                // 페이지를 계속 파싱할지 여부
        var $_set_cookies            = '';                // 쿠키 저장
        var $_set_referer                = '';                // 레퍼러 저장
        var $_skip_offset                = array();        // 건너뛸 문장
        var $_wait                            = 0;                // 한페이지 처리후 멈춤시간(단위 초)

        function voidSetPattern($field,$token_start,$token_end,$del_str='') {
            /********************************************************************
            * public
            * 파싱할 패턴문자 설정
            * ex) $buf->voidSetPattern(필드명,시작문자,끝문자,[지울문자]);
            *
            * 텍스트 내용중 < 와 > 사이에 있는 문자열을 name 이라는 이름으로 빼내고
            * 결과문자열중 \ 를 지우고자 하는경우
            * ex) $buf->voidSetPattern('name','<','>','\');
            ********************************************************************/
            if($field == '_default_')
                $this->voidError('_default_ 는 사용할수 없는 단어입니다.' );

            $this->_parse_pattern[$field] = array($token_start,$token_end,$del_str);
        }

        function voidSetSkipOffset($field,$token) {
            /********************************************************************
            * public
            * 파싱후 패턴과 동일한 문자가 중간에 존재하여 그부분의 뒷부분 부터 파싱을 원할경우
            * ex) $buf->voidSetSkipOffset(필드명,찾을문자);
            *
            * name 필드 파싱후 다음 파싱 패턴과 동일한 문자가 있을경우 건너뜀
            * ex) $buf->voidSetSkipOffset('name','<');
            *
            * 필드명을 _default_ 라고 설정할경우 파싱전 해당 문자로 이동을 한후에
            * 파싱을 시작함. default 시작위치를 설정
            * ex) $buf->voidSetSkipOffset('_default_','<');
            ********************************************************************/
            $this->_skip_offset[$field] = $token;
        }

        function voidSetCookie($var,$value) {
            /********************************************************************
            * public
            * 쿠키를 설정합니다.
            * ex) $buf->voidSetCookie(쿠키명,쿠키값);
            ********************************************************************/
            $this->_set_cookies .= $var.'='.urlencode($value).';';
        }

        function voidSetReferer($ref) {
            /********************************************************************
            * public
            * 레퍼러를 설정합니다.
            * ex) $buf->voidSetReferer(레퍼러);
            ********************************************************************/
            $this->_set_referer = $ref;
        }

        function voidSetPage($var,$func='',$page=1) {
            /********************************************************************
            * public
            * 페이지 처리를 원할경우 설정
            * ex) $buf->voidSetPage(페이지변수명,[외부처리함수],[시작페이지]);
            * 하나의 주소에 연속된 페이지가 존재할경우 계속 읽어들일수 있습니다.
            *
            * 페이지변수 pagenum=1,2,3,4,5 식으로 페이지가 존재하는 경우
            * ex) $buf->voidSetPage('pagenum','func',1);
            *
            * 주의) 페이지가 많을경우 배열에 결과값이 계속 쌓이므로 리소스가 커질수 있으니
            * 생성자에 설정할수 있는 외부 함수를 이용하여 페이지 마다 바로 처리하시기 바라며
            * 역시나 시간이 오래 걸릴수 있으니 쉘모드에서 실행하시기 바랍니다.
            ********************************************************************/
            $this->_page_var = $var;
            $this->_page_no = $page;
            $this->_process_func = $func;
        }

        function voidSetSleep($sec) {
            /********************************************************************
            * public
            * 페이지 처리시 완료후 잠시 멈춰있을 시간입니다.
            * ex) $buf->voidSetSleep(초);
            ********************************************************************/
            $this->_wait = $sec;
        }

        function voidGetAllContents($url,$method = 'get',$port = '80') {
            /********************************************************************
            * public
            * 전체 페이지 내용을 긁어오는 부분입니다.
            * ex) $buf->voidGetAllContents(주소,[메소드],[포트]);
            *
            * 결과 값은
            * $buf->response_header; 응답헤더만 별도 저장
            * $buf->contents; 전체페이지 내용저장
            ********************************************************************/
            if($method != 'get' && $method != 'post')
                $this->voidError('method 값이 다릅니다. '.$method);

            $url_info = parse_url($url);
            $fp = fsockopen($url_info['host'], $port, $errno, $errstr);
            if(!$fp) {
                $this->voidError($errstr.' ('.$errno.')');
            }
            
            if($method == 'post')    {
                fputs($fp,"POST ".$url_info['path']." HTTP/1.0\r\n");
                fputs($fp,"Host: ".$url_info['host']."\r\n");
                fputs($fp,"User-Agent: PHP Script\r\n");

                if($this->_set_referer)
                    fputs($fp,"Referer: ".$this->_set_referer."\r\n");

                if($this->_set_cookies)
                    fputs($fp,"Cookie: ".$this->_set_cookies."\r\n");

                fputs($fp,"Content-Type: application/x-www-form-urlencoded\r\n");
                fputs($fp,"Content-Length: ".strlen($url_info['query'])."\r\n");
                fputs($fp,"Connection: close\r\n\r\n");
                fputs($fp,$url_info['query']);
            }
            else {
                fputs($fp,"GET ".$url_info['path'].($url_info['query'] ? '?'.$url_info['query'] : '')." HTTP/1.0\r\n");
                fputs($fp,"Host: ".$url_info['host']."\r\n");
                fputs($fp,"User-Agent: PHP Script\r\n");

                if($this->_set_referer)
                    fputs($fp,"Referer: ".$this->_set_referer."\r\n");

                if($this->_set_cookies)
                    fputs($fp,"Cookie: ".$this->_set_cookies."\r\n");

                fputs($fp,"Connection: close\r\n\r\n");
            }

            $this->contents = '';
            $this->response_header = '';

            while(trim($buf = fgets($fp,1024)) != "") { //응답헤더를 읽어옵니다.
                $this->response_header .= $buf;
            }

            while(!feof($fp)) { //내용을 읽어옵니다.
                $this->contents .=  fgets($fp,1024);
            }
            fclose($fp);
        }

        function voidParsePage($url,$method = 'get',$port = '80') {
            /********************************************************************
            * public
            * 파싱하는 부분 main 이 되겠습니다.
            * 페이징 처리와 계속 파싱할것인지 결정을 하고
            * 외부함수 처리 역시 여기서 합니다.
            * ex) $buf->voidParsePage(주소,[메소드],[포트]);
            *
            * _default_ 오프셋이 있으면 그쪽으로 이동시키고 패턴에 등록된 것만큼 반복을 합니다.
            * name,img,price 패턴이 등록되 있다면
            * name파싱,img파싱,price파싱을 계속 반복합니다.
            * 더이상 내용이 없다면 종료시키거나 페이지설정이 되있다면
            * 다음페이지를 읽어들여서 다시 파싱을 반복하고 페이지가 없을때까지 반복 파싱.
            ********************************************************************/
            $this->_roop = 1;
            $page_now = $this->_page_no;
            $page = '';
            $key = array_keys($this->_parse_pattern);
            $cnt=count($key);

            while($this->_roop) {
                $this->_goods_no = 0;
                $this->_offset = 0;
                $parse_count = 0;
                $this->voidGetAllContents($url.$page,$method,$port);
            
                if($this->_skip_offset['_default_'])
                    $this->voidGetOffset($this->_skip_offset['_default_']);

                if($this->_roop) {
                    while($this->_roop) {
                        for($i=0;$i<$cnt;$i++) {
                            $this->voidGetText($key[$i]);
                            if(!$this->_roop) {
                                if($cnt != count($this->parse_value[$this->_goods_no]))
                                    unset($this->parse_value[$this->_goods_no]);
                                break;
                            }
                            $parse_count++;
                        }
                        $this->_goods_no++;
                    }
                }

                if($this->_page_var) {
                    if($parse_count >= $cnt) {
                        $page = '&'.$this->_page_var.'='.(++$page_now);
                        $this->_roop = 1;
                        if($this->_wait)
                            sleep($this->_wait);
                    }
                    else {
                        $this->_roop = 0;
                        break;
                    }
                }
                
                if($this->_process_func) {
                    call_user_func($this->_process_func,$this->parse_value);
                    $this->parse_value = array();
                }
            }
        }

        function voidGetOffset($str) {
            /********************************************************************
            * private
            * 검색위치를 건너뛰는 부분입니다.
            * ex) $buf->voidGetOffset(문자);
            * 해당문자가 없으면 종료합니다.
            ********************************************************************/
            $tmp_offset = strpos($this->contents,$str,$this->_offset);
            if($tmp_offset)
                $this->_offset = $tmp_offset + strlen($str);
            else
                $this->_roop = 0;
        }

        function voidGetText($field) {
            /********************************************************************
            * private
            * 패턴 사이의 문자열을 추출하는 부분입니다.
            * ex) $buf->voidGetText(필드);
            * 역시나 해당문자가 없으면 종료합니다.
            ********************************************************************/
            $spos = strpos($this->contents,$this->_parse_pattern[$field][0],$this->_offset);
            if(!$spos) {
                $this->_roop = 0;
                return;
            }
            $spos += strlen($this->_parse_pattern[$field][0]);

            $epos = strpos($this->contents,$this->_parse_pattern[$field][1],$spos);
            if(!$epos) {
                $this->_roop = 0;
                return;
            }
            $this->_offset = $epos + strlen($this->_parse_pattern[$field][1]);

            $str = substr($this->contents,$spos,$epos-$spos);

            if($this->_parse_pattern[$field][2])
                $this->parse_value[$this->_goods_no][$field] = str_replace("\r\n",'',str_replace($this->_parse_pattern[$field][2],'',trim($str)));
            else
                $this->parse_value[$this->_goods_no][$field] = str_replace("\r\n",'',trim($str));

            if($this->_skip_offset[$field])
                $this->voidGetOffset($this->_skip_offset[$field]);
        }

        function voidError($msg) {
            exit($msg);
        }
    }
    ?>

    웹페이지에서 필요한 부분만 가져오는 프로그램을 클래스로 만들어서
    조금이라도 쉽고 편하게 가져올수 있도록 만들어 봤습니다.
    아 이거 만들때는 스누피가 있는걸 몰라서 걍 만든거니
    스누피 쓴다니 만다니 라고 말씀하시면 상처입습니다 -ㅂ-;

    간단한 사용설명은-------------------------------------------------------------------
    $buf = new GalKuRi;  //객체생성
    $buf->voidSetCookie(쿠키명,쿠키값); //쿠키설정
    $buf->voidSetReferer(레퍼러); //레퍼러설정
    $buf->voidSetPage(페이지변수명,외부함수,페이지번호); //페이지 처리 설정 외부함수는 한페이지후 결과를 처리하기 위해 설정
    $buf->voidSetSleep(초); //한페이지 처리수 정지시간
    $buf->voidSetPattern(필드명,시작문자,끝문자,[지울문자]); //파싱할 패턴 설정 시작문자와 끝문자 사이의 문자열을 배열로 저장
    $buf->voidSetSkipOffset(필드명,찾을문자); //파싱후 패턴에 넣은 문자와 동일한 문자가 있어서 방해될경우 그문자까지 오프셋을 뛰어 넘음
    $buf->voidParsePage(주소,[메소드],[포트]); //파싱시작

    #
    # 파싱된 데이타를 처리하는 방법
    #
    $buf->parse_value 배열을 처리하면 됨

    #
    # voidSetPage('page','func',1) 에서 외부 함수를 설정했을경우
    # 한페이지 처리시는 괜찬으나 페이지가 많으면 배열이 많이 늘어나니
    # 페이지가 많을 경우에는 외부 함수 사용을 추천
    #
    function func(&$val) {
      $val 결과배열 처리
    }

    ----------------------------------------------------------------------------
    #
    # 참고
    # 단순히 전체페이지 내용을 원할경우(voidSetPattern 불필요)
    #

    $buf = new GalKuRi;
    $buf->voidSetCookie(쿠키명,쿠키값);
    $buf->voidSetReferer(레퍼러);
    $buf->voidGetAllContents(주소,[메소드],[포트]);
    echo $buf->response_header; //헤더값
    echo $buf->contents; //전체내용

    ----------------------------------------------------------------------------
    간단한 예제 몇개.

    스쿨 팁텍 목록 가져오기

    function voidPrint(&$val) {
     print_r($val);
    }

    $buf = new GalKuRi;
    $buf->voidSetPage('page','voidPrint',1);
    $buf->voidSetSkipOffset('_default_','<!-- 목록 -->');
    $buf->voidSetPattern('num','<td id="bb_list">','<');
    $buf->voidSetPattern('kind','<span class=small>','<');
    $buf->voidSetPattern('view_url',"<a href='..","'");
    $buf->voidSetPattern('title',"<span style=''>","<");
    $buf->voidSetPattern('name','title="','"');
    $buf->voidSetPattern('regtime','title="','"');
    $buf->voidSetPattern('regdate','>','<');
    $buf->voidSetPattern('hit','<td id="bb_list">','<');


    $buf->voidParsePage('http://www.phpschool.com/gnuboard4/bbs/ ··· e%3D1%27);
     

    디엡숍 상품 리스트(tv였나.. ㅡㅡ;;) 가져오기
    function voidPrint(&$val) {
     print_r($val);
    }

    $buf = new GalKuRi;
    $buf->voidSetPage('DTYPE=IMAGE&pageNo=','voidPrint',1);
    $buf->voidSetSkipOffset('_default_','<form name="prodlist"');
    $buf->voidSetCookie('ACODE','1ltjzE.wkt10');
    $buf->voidSetCookie('tcateid','D42414');
    $buf->voidSetCookie('pmmcBGIBLE8BRMUSEGM2B78CVG78KJ4','0');
    $buf->voidSetCookie('pmmczGIBLE8BRMUSEGM2B78CVG78KJ4','1');
    $buf->voidSetPattern('image_url','<img src="http://shopimage.hanmail.net/m_productimages/','"');
    $buf->voidSetPattern('content_url','<a href="','"');
    $buf->voidSetPattern('goods_name','>','</a>');
    $buf->voidSetPattern('price','<strong class="price">','원',',');
    $buf->voidParsePage('http://dnshop.daum.net/front/category/d ··· 42414%27);

    옥션 상품리스트 (무슨상품이었더라... ㅡㅡ;;) 가져오기
    function voidPrint(&$val) {
     print_r($val);
    }

    $buf = new GalKuRi;
    $buf->voidSetPage('page','voidPrint',1);
    $buf->voidSetSkipOffset('_default_','<table class="listView" border="0" cellpadding="0" cellspacing="0" align="NotSet" style="width: 900px" >');
    $buf->voidSetPattern('image',"<img src='","'",'');
    $buf->voidSetPattern('content',"<a target=\"_top\" href='","'",'');
    $buf->voidSetPattern('name','class="itemName">','</a>','');
    $buf->voidSetPattern('price','<div style="FONT-WEIGHT: bold; COLOR: #ff8004">','</div>',',');
    $buf->voidParsePage('http://listings.auction.co.kr/category/ ··· Dhome%27);

    네이버 검색 결과페이지 관련키워드 가져오기
    $buf = new GalKuRi;
    $buf->voidSetSkipOffset('_default_','<div class="SuggestWord">');
    $buf->voidSetPattern('keyword',')));">','<');
    $buf->voidSetSkipOffset('keyword','rsk.list1');
    $buf->voidParsePage('http://search.naver.com/search.naver?wh ··· rlencode('아디다스').'&frm=t1&sm=top_hty');

    print_r($buf->parse_value);
    2010/04/15 17:08 2010/04/15 17:08
    이 글의 관련글

    Trackback Address : http://www.1go.co.kr/blog/trackback/3714

    [로그인][오픈아이디란?]
    안주꺼리 2010/04/13 17:34
  • 글라스우드 - 난연, 무독성, 방부, 방충, 치수안정성, 강도, 내구성 등 탁월한 성능을 발휘하도록 만든 불용성 목재
  • <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <title>test</title>
    <meta http-equiv="Progma" content="on-cache" />
    <meta http-equiv="Expires" content="-1" />
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <meta name="viewport" content="initial-scale=1.0; maximum-scale=1.0; minimum-scale=1.0; user-scalable=no;" />
    <style type="text/css">
    #stage {
        border:1px #DDD solid;
    }

    #link{
        text-align:center;
        border:2px solid;
        border-color:red;
    }

    #closed{
        border:1px solid;
    }
    </style>
    <script type="text/javascript" src="jquery.js"></script>
    <script type="text/javascript">
    var started = false;
    var canvas, context;

    //초기화 함수
    function init(){
        canvas = document.getElementById('stage');
        context = canvas.getContext('2d');
        started = false;

        //아이폰인지 판별
        var ua = navigator.userAgent;
        if(ua.indexOf('iPhone') > 0){
         
            canvas.addEventListener('touchstart', function(e){
                context.beginPath();
                context.moveTo(e.targetTouches[0].pageX - 8, e.targetTouches[0].pageY - 8);
                started = true;
            });


            canvas.addEventListener('touchmove', function(e){
                if(started  == true){
                    e.preventDefault();
                    context.lineTo(e.targetTouches[0].pageX - 8, e.targetTouches[0].pageY - 8);
                    context.stroke();
                }
                $("#debug").html(e.targetTouches[0].pageX  + "/ " + e.targetTouches[0].pageY );
            });


            canvas.addEventListener('touchend', function(e){
                if(started  == true){
                    started = false;
                }
            });

        }else{

            canvas.onmousedown = function(e){
                context.beginPath();
                context.moveTo(e.clientX - 8, e.clientY - 8);
                started = true;
            };

            canvas.onmousemove = function(e){
                if(started  == true){
                    context.lineTo(e.clientX - 8, e.clientY - 8);
                    context.stroke();
                }
            };

            canvas.onmouseup = function(e){
                if(started == true){
                    started = false;
                }
            };

        }//end else
    };//end init();


    //이미지 추출
    function ExtractImage(){
        var strDataURI = canvas.toDataURL("image/jpeg");

        //이미지 데이타를 전송후 php에서 이미지로 저장
        $.ajax({
            type: "POST",
            url : "ExtractImage.php",
            data : { data : strDataURI },
            success : function(data){
                $("#image").html(data);
                $("#image").append('<img src="' + strDataURI + '">');
                $("#link").css({ "display" : "block" });
            }
        });
    }



    $(function(){

        init(); //초기화실행

        //클릭시 레이어 닫기
        $("#closed").click(function(){
            $("#link").css({ "display" : "none" });
            $("#image").html("");
        });

    });

    </script>
    </head>
    <body>
        <div id="container">
            <canvas id="stage" width="300" height="270"></canvas>
        </div>
        <a href="javascript:ExtractImage();">이미지출력</a>
        <a href="javascript:document.location.reload();">초기화</a>
        <br><br>
        <div id="link" style="display:none;">
            <div id="image">
            </div>
            <span id="closed">닫기</span>
            <br><br>
        </div>
        <div id="debug"></div>
    </body>
    </html>

    이미지를 저장하는쪽은

    //해당 이미지 저장
    session_start();
    $name = session_id();
    $dataurl = str_replace(" ", "+", $_POST["data"]);
    $data = substr($dataurl, strpos($dataurl , ","));
    $file = fopen("./image/".$name.".jpg", "wb");
    fwrite($file, base64_decode($data));
    fclose($file);


    echo "<br><a href=\"http://drst3in.potatoweb.net/iphone/image/".$name.".jpg\">
            이미지 다운로드
        </a>";

    --------------------------------------------------------------------------------
    2010/04/13 17:34 2010/04/13 17:34
    이 글의 관련글

    Trackback Address : http://www.1go.co.kr/blog/trackback/3690

    [로그인][오픈아이디란?]