컴퓨터 얘기/프로그래밍 : 해당되는 글 61건

2010/03/05 >> iPhone 에서 OAuth 라이브러리 사용하기 (2)
2007/12/07 >> Read Me 플러그인 (3)
2007/11/28 >> 드림위버와 이별하기 (5)
2007/04/09 >> MySQL Foreign Key 바보짓 (6)
2007/02/07 >> TinyMCE 플러그인 - WikiExporter (5)
2007/02/04 >> 멜론 앨범 커버 다운로더 (20)
2007/02/03 >> Crizin.HTTPRequest.php (8)
2006/08/21 >> preg 계열 함수들의 버그? (10)
2006/08/11 >> IE 6.0의 버그들 (7)
2006/05/09 >> 태터툴즈 1.0.5 플러그인 (58)
2006/03/22 >> 태터툴즈 방문자 그래프 플러그인 (9)
2005/10/04 >> 태터툴즈에 FTP로 첨부파일 올리기 (11)
2005/09/15 >> 자바스크립트에서 문자열을 합치는 방법 (2)
2005/09/13 >> 태터툴즈 + BBClone의 10원짜리 팁 (5)
2005/09/13 >> 태터툴즈 답글 + 기타등등을 RSS로 (21)
2005/08/16 >> Konfabulator Widget 만들기 (26)
2005/08/16 >> 태터툴즈 답글 삭제부분 수정 (8)
2005/08/15 >> 태터툴즈 0.96 위치로그 업데이터 (9)
2005/08/13 >> 태터툴즈 0.96용 노가다 유틸 (5)
2005/08/12 >> 태터툴즈용 간단한 통계 그래프 (9)
2005/08/11 >> 실용예제로 배우는 웹표준 (7)
2005/08/09 >> Google Talk (8)
2005/07/21 >> 우라질 쫀듸기같은 GD (3)
2005/07/15 >> MSN으로 태터툴즈 댓글 알림받기 (16)
2005/06/14 >> 인터넷 만화 RSS 몇개 (14)
2005/06/12 >> 태터툴즈 고쳐쓰기 #12 - 답글에 국가 아이콘 표시하기 (29)
2005/06/04 >> 태터툴즈용 Google Sitemap (12)
2005/04/27 >> 날씨를 보여주는 자바스크립트 (6)
2005/04/19 >> 200년 달력
2005/04/02 >> 태터툴즈 고쳐쓰기 #11 - UTF-8 RSS 읽기, 트랙백 보내기 (10)

iPhone 에서 OAuth 라이브러리 사용하기

지난 주에 아이폰에 OAuth 컨슈머 라이브러리 돌리는데 삽질을 너무 많이 해서 반성하는 의미로 포스팅 해본다. http://oauth.net에 있는 라이브러리는 아이폰에 바로 쓸 수 없어서 약간 손을 봐야하는데 누군가 이미 해놓은 것도 있지만 기본(?) 라이브러리로 한번 해봤다. 붙이는건 그렇게 어렵지 않은데 아이폰에 써드파티 바이너리 프레임웍 추가 안되는거랑 Security.framework 내용이 Mac의 것과 다르다는 걸 몰라서 시간을 엄청 허비했음.

  1. OAuthConsumer 라이브러리를 체크아웃 한다.

    svn checkout http://oauth.googlecode.com/svn/code/obj-c/ .

  2. 프레임웍으로 빌드해서 넣으면 깔끔하겠지만 아이폰에는 그렇게 넣을 수 없으니 소스를 직접 넣는다. 다운받은 OAuthConsumer 디렉토리 아래에서 필요한 파일만 남기고 모두 삭제한다.

    rm -rf English.lproj OAuthConsumer.xcodeproj *.plist *.pch *.rb *Test.?

  3. Xcode에서 OAuthTest 라는 이름의 View-Based Application 하나를 생성한다.

  4. Finder에서 OAuthConsumer 디렉토리를 끌어다 Groups & Files 창의 Classes 아래에 놓는다. 파일을 복사할꺼니까 끌어다 놓을때 뜨는 'Copy items into destination group's folder'에 체크하고 Add 한다.

  5. 이 상태에서 빌드를 해보면 OAToken_KeychainExtensions.m 파일에서 에러가 난다. 원래 Mac Cocoa 환경이라면 Security.framework 라이브러리를 추가해서 컴파일 할 수 있지만 아이폰용 Security.framework 라이브러리는 맥용과 달라서 OAToken_KeychainExtensions.m 파일을 컴파일 시킬 수 없다. 하지만 이 파일은 꼭 필요한건 아니고 나중에 OAuth 인증 끝나고 토큰과 시크릿을 키체인에 안전하게 보관할 수 있게 도와주는 유틸리티인데 필요하면 알아서 구현하고 일단 지워도 문제 없다. 파일 목록에서 OAToken_KeychainExtensions.? 파일을 삭제하고 빌드하면 일단 문제없이 컴파일이 될 것이다.

  6. 시작하기 전에 OAuthConsumer.h 파일을 열어서 import 경로를 올바른 경로로 바꾸어주자.

    #import <Foundation/Foundation.h> #import <OAuthConsumer/OAToken.h> #import <OAuthConsumer/OAConsumer.h> #import <OAuthConsumer/OAMutableURLRequest.h> ...

    이걸 아래처럼 변경.

    #import <Foundation/Foundation.h> #import "OAToken.h" #import "OAConsumer.h" #import "OAMutableURLRequest.h" ...

  7. 이제 OAuthTestViewController.xib 파일을 열어서 아래 그림처럼 웹뷰, 'Get Request Token' 버튼, 'Get Access Token' 버튼, PIN 번호를 입력받을 텍스트 필드가 있는 화면을 생성한다. 'Get Request Token' 버튼을 누르면 Request Token을 얻어와서 트위터의 Authorize URL로 이동시키고, 사용자가 로그인 한 후 보여지는 PIN 번호를 넣고 'Get Access Token' 버튼을 누르면 Access Token을 가져올 것이다.

  8. 위에서 추가한 웹뷰, 텍스트필드의 아웃렛 변수와 두 버튼에 연결될 액션 메서드를 만들고 연결한다.

    #import <UIKit/UIKit.h> @interface OAuthTestViewController : UIViewController { UIWebView *webView; UITextField *textField; } @property (nonatomic, retain) IBOutlet UIWebView *webView; @property (nonatomic, retain) IBOutlet UITextField *textField; - (IBAction)requestTokenButton:(UIButton *)sender; - (IBAction)accessTokenButton:(UIButton *)sender; @end

  9. 먼저 'Get Request Token' 버튼을 눌렀을때 Request Token을 얻어와서 로그에 찍어보자. 아래처럼 호출하도록 requestTokenButton: 메서드를 작성하고 성공/에러시에 호출될 델리게이트 메서드도 만든다.

    #import "OAuthConsumer.h" ... - (IBAction)requestTokenButton:(UIButton *)sender { OAConsumer *consumer = [[OAConsumer alloc] initWithKey:@"Z0DxPl4q7kmSOgh3LTpV4Q" secret:@"LWryiOYBAHJ58PX9Yn1yG5bzDwpMJiksqpXxfst7kcU"]; NSURL *url = [[NSURL alloc] initWithString:@"http://twitter.com/oauth/request_token"]; OAMutableURLRequest *request = [[OAMutableURLRequest alloc] initWithURL:url consumer:consumer token:nil realm:@"http://twitter.com/" signatureProvider:nil]; [request setOAuthParameterName:@"oauth_callback" withValue:@"oob"]; OADataFetcher *fetcher = [[OADataFetcher alloc] init]; [fetcher fetchDataWithRequest:request delegate:self didFinishSelector:@selector(requestTokenTicket:didFinishWithData:) didFailSelector:@selector(requestTokenTicket:didFailWithError:)]; [consumer release]; [url release]; [request release]; [fetcher release]; } - (void)requestTokenTicket:(OAServiceTicket *)ticket didFinishWithData:(NSData *)data { if (ticket.didSucceed) { NSString *responseBody = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; OAToken *token = [[OAToken alloc] initWithHTTPResponseBody:responseBody]; NSLog(@"Request Token: key=%@, secret=%@", [token key], [token secret]); [token release]; [responseBody release]; } else { NSLog(@"Finish but did not succeed."); } } - (void)requestTokenTicket:(OAServiceTicket *)ticket didFailWithError:(NSError *)error { NSLog(@"Error: %@", [error localizedDescription]); }

    위와 같이 작성해서 실행해보면 requestTokenTicket:didFailWithError: 쪽으로 떨어지면서,

    Operation could not be completed. (NSURLErrorDomain error -1012.)

    이런 메시지가 떨어진다. 이유는,

    [request setOAuthParameterName:@"oauth_callback" withValue:@"oob"];

    이 부분 때문인데 oauth_callback 이라는 파라미터를 추가하고 싶어서 이렇게 적었으면 이 파라미터를 포함하여 시그니쳐를 생성해야 하는데 OAuthConsumer 라이브러리에서는 추가된 파라미터를 제외하고 시그니처를 생성해 요청했고 결과적으로 트위터에서 시그니처가 틀리다는 이유로 200 OK가 떨어지지 않는 상태이다(버그이거나 OAuth 1.0a 스펙을 고려하지 않아서인 듯). 추가된 파라미터를 포함하여 시그니처를 생성하도록 OAMutableURLRequest.m 파일을 수정해보자. 파일을 열어서 _signatureBaseString 메서드 중간쯤에,

    ... for (OARequestParameter *param in [self parameters]) { [parameterPairs addObject:[param URLEncodedNameValuePair]]; } for(NSString *parameterName in [[extraOAuthParameters allKeys] sortedArrayUsingSelector:@selector(compare:)]) { [parameterPairs addObject:[[OARequestParameter requestParameterWithName:parameterName value:[extraOAuthParameters objectForKey:parameterName]] URLEncodedNameValuePair]]; } NSArray *sortedPairs = [parameterPairs sortedArrayUsingSelector:@selector(compare:)]; NSString *normalizedRequestParameters = [sortedPairs componentsJoinedByString:@"&"]; ...

    이렇게 for 루프를 하나 추가한다. 이제 다시 실행해서 'Get Request Token' 버튼을 눌러보면,

    2010-03-05 17:09:40.438 OAuthTest[1691:207] Request Token: key=wyGw0VUSE79MTuVm0iqs7ZdWiPI3ZRJWCZ2k6P73w, secret=AUGrkHfx3nr6xb9Q5dUbNQzykZQvFJ62WW90BojT8

    콘솔에 이렇게 찍히면서 정상적으로 토큰을 얻어올 수 있다.

  10. 이제 Request Token을 얻어왔으니 토큰을 임시로 저장하고 트위터의 Authorize URL을 호출한다. 아래처럼 OAuthTestViewController.h 파일을 수정하고,

    #import <UIKit/UIKit.h> @class OAServiceTicket; @class OAToken; @interface OAuthTestViewController : UIViewController { UIWebView *webView; UITextField *textField; OAToken *requestToken; } @property (nonatomic, retain) IBOutlet UIWebView *webView; @property (nonatomic, retain) IBOutlet UITextField *textField; @property (nonatomic, retain) OAToken *requestToken; ...

    아래처럼 OAuthTestViewController.m 파일을 수정한다.

    if (ticket.didSucceed) { NSString *responseBody = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; OAToken *token = [[OAToken alloc] initWithHTTPResponseBody:responseBody]; NSLog(@"Request Token: key=%@, secret=%@", [token key], [token secret]); self.requestToken = token; [token release]; [responseBody release]; NSString *authorizeURL = [[NSString alloc] initWithFormat:@"http://twitter.com/oauth/authorize?oauth_token=%@", [self.requestToken.key URLEncodedString]]; [self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:authorizeURL]]]; [authorizeURL release]; } ...

    이제 실행하고 'Get Request Token' 버튼을 누르면 아래 이미지 처럼 인증을 요구하는 화면이 나오고 Allow 하고 나면,

    아래 이미지 처럼 PIN 번호가 보여진다.

  11. 이제 PIN 번호를 입력하고 'Get Access Token'을 클릭했을 때의 처리를 하면 된다. accessTokenButton: 메서드를 아래처럼 작성하고 accessTokenTicket:didFinishWithData:, accessTokenTicket:didFailWithError: 델리게이트 메서드도 만들자.

    - (IBAction)accessTokenButton:(UIButton *)sender { OAConsumer *consumer = [[OAConsumer alloc] initWithKey:@"Z0DxPl4q7kmSOgh3LTpV4Q" secret:@"LWryiOYBAHJ58PX9Yn1yG5bzDwpMJiksqpXxfst7kcU"]; NSURL *url = [[NSURL alloc] initWithString:@"http://twitter.com/oauth/access_token"]; OAMutableURLRequest *request = [[OAMutableURLRequest alloc] initWithURL:url consumer:consumer token:self.requestToken realm:@"http://twitter.com/" signatureProvider:nil]; [request setOAuthParameterName:@"oauth_verifier" withValue:self.textField.text]; OADataFetcher *fetcher = [[OADataFetcher alloc] init]; [fetcher fetchDataWithRequest:request delegate:self didFinishSelector:@selector(accessTokenTicket:didFinishWithData:) didFailSelector:@selector(accessTokenTicket:didFailWithError:)]; [consumer release]; [url release]; [request release]; [fetcher release]; } - (void)accessTokenTicket:(OAServiceTicket *)ticket didFinishWithData:(NSData *)data { if (ticket.didSucceed) { NSString *responseBody = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; OAToken *token = [[OAToken alloc] initWithHTTPResponseBody:responseBody]; NSLog(@"Got Access Token [key:%@, secret:%@]", token.key, token.secret); [token release]; [responseBody release]; } else { NSLog(@"Finish but did not succeed."); } } - (void)accessTokenTicket:(OAServiceTicket *)ticket didFailWithError:(NSError *)error { NSLog(@"Error: %@", [error localizedDescription]); }

  12. 이제 실행해서 PIN 번호를 넣고 'Get Access Token' 버튼을 누르면 아래처럼 Access Token 정보가 콘솔에 출력된다.

    Got Access Token [key:14368376-CyPcPg7uVLcOkzRJBlJLMVKqZQMzCMQnRxHMmzQG8, secret:HY3eENZ6Pt4AFdUUtzAROlZDaKHOJHtcc7lMKMyKE]

  13. 이제 위에서 출력되는 Access Token 정보를 저장해서 OAMutableURLRequest 클래스로 요청 할 때 token 인자에 넣어 보내면 된다. 요청 할 때 파라미터를 세팅해야 할 경우에는, OARequestParameter 파라미터를 NSArray 로 묶어 OAMutableURLRequest 생성 후에 setParameter: 해주면 된다.

틀린 내용이 있다면 지적해주세요!

'컴퓨터 얘기 > 프로그래밍' 카테고리의 다른 글

iPhone 에서 OAuth 라이브러리 사용하기  (2) 2010/03/05
Read Me 플러그인  (3) 2007/12/07
드림위버와 이별하기  (5) 2007/11/28
MySQL Foreign Key 바보짓  (6) 2007/04/09
TinyMCE 플러그인 - WikiExporter  (5) 2007/02/07
멜론 앨범 커버 다운로더  (20) 2007/02/04

Read Me 플러그인

구글 리더설정 » 추가기능 메뉴에 가보면 '다음'이라는 링크가 있고 이걸 즐겨찾기에 추가해서 클릭하면 리더의 안읽은 글을 하나씩 꺼내 포스트를 보여준다. 꽤 편리한 기능이라 구글 리더를 본격적으로 써보려고 RSS들을 등록하고 정리를 열심히 해봤으나 리더 자체가 꽤 느리고 꺼내오는 글이 시간 역순 정렬이 아니라 GG. 그냥 텍큐 리더에 이런 기능을 넣는게 낫겠다 싶어서 한참을 부비작거려 나온 물건이 바로 이놈.

설치한 다음 플러그인 환경설정 창을 열면 '피드 보기'라는 링크가 있는데 이걸 즐겨찾기에 추가해서 쓰면 된다. '로그인을 해야 사용할 수 있게 합니다'로 설정하면 처음 누를때 로그인해야 쓸 수 있으니 결벽증이 있으신 분들은 이쪽을 쓰시고 나머지 분들은 링크가 노출되지 않도록 주의해서 사용하면 됨. 더이상 읽을게 없으면 이상한 페이지가 나와요.

내경우엔 이걸 WebMa 플러그인으로 만들어놓고 마우스 제스쳐에 등록해서 ㄱ자를 그리면 포스트가 하나 튀어나오도록 해놨는데 일하다가 딴짓하기 매우 좋다.

'컴퓨터 얘기 > 프로그래밍' 카테고리의 다른 글

iPhone 에서 OAuth 라이브러리 사용하기  (2) 2010/03/05
Read Me 플러그인  (3) 2007/12/07
드림위버와 이별하기  (5) 2007/11/28
MySQL Foreign Key 바보짓  (6) 2007/04/09
TinyMCE 플러그인 - WikiExporter  (5) 2007/02/07
멜론 앨범 커버 다운로더  (20) 2007/02/04

드림위버와 이별하기

소스 저장소로 SVN을 쓰고 로컬 하드디스크에 이 소스를 다운로드해 수정한 다음 원격의 개발서버에 FTP 등으로 즉각 업로드해 테스트하고 로컬에서 TortoiseSVN 등을 이용해 소스를 커밋해 완료한다. 웹개발 하는 일반적인 방법에서 크게 벗어나는건 없지 않나 싶은데도 이렇게 작업하는 사람들은 그리 많지 않나보다. 작업하는 PC에 개발에 필요한 서버들을 세팅해서 작업하고 실제 서버와 비슷한 환경에서의 개발하는 사람들이 가장 많아보이는데 그래도 실서비스와 최대한 같은 환경에서 개발하는게 배포했을때 이기종간의 미묘한 삑사리를 줄여줄 수 있는 방법이라고 아직까지는 생각된다.

그래서 이런 환경에서 어떤 에디터나 IDE를 쓰는게 가장 편하냐고 하면 우울하게도 드림위버 말고는 쓸만한게 없다. 이놈을 써야하는 거의 유일한 이유는 PC의 디렉토리와 원격 FTP 사이트의 디렉토리를 매칭시켜서 파일을 수정하면 바로바로 업로드 해주는 에디터라는건데 지금까지도 이런일을 해주는 에디터를 계속 찾아봤지만 드림위버처럼 깔끔하게 처리해주는 에디터는 없는 것 같다. 에디트플러스 같은 에디터는 여러 파일 작업하기도 불편하거니와 원격이나 로컬 한쪽의 파일만 수정 가능해서 쓸 수 없고 이클립스는 FTP 사이트와 로컬 디렉토리간이 매칭은 가능하지만 실시간 저장이 안되고 양쪽의 변경된 파일을 Sync 해주는 기능만 있는데 이래가지고서야 파일 수정 한번하고 한세월 기다려야 하니 역시 곤란하다. (rsync를 이용해 업로드하는게 차라리 빠르다. Ant를 이용해 빌드 파일 만들어놓고 단축키에 걸어서 while(!퇴근) { 수정하고; 저장하고; sync; 확인하고; } 하면 원츄라고 함)

그런 이유로 드림위버를 떠나고 싶어도 떠날수 없던 세월 가운데..

그나마 가장 가능성 높은 대안이었지만 불안정하고 무겁고 어렵다는 이유로 눈밖에 있던 Aptana를 다시 테스트해봤는데 이제는 주력 개발툴로 사용해도 별 문제가 없을 정도로 안정되어졌고 결정적으로 드림위버의 'Upload file on save' 기능을 간접적으로나마 지원하기 시작했다. 벌써 한참 전에 이런 기능의 요구가 있었고 Eclipse Monkey(Aptana Monkey?) 플러그인을 통해 Save command가 일어날때 Upload가 이루어지도록 할 수 있게 됐다. (메뉴의 Save를 클릭하거나 CTRL-S를 누를때만 실행이 돼서 나처럼 ALT-F,S로 저장하는 사람은 살짝 불편할 수 있다.)

PHP 개발환경에 있어서는 이클립스에 PDT 깔아서 쓰는거보다는 못하지만 드림위버에 비하면야 많이 좋다. 좀 무거운거야 드림위버 살돈으로 좋은 CPU와 메모리를 사서 해결하면되..나?; 이클립스가 베이스인만큼 Subclipse나 Mylyn 같은거 쓰면 근사하지만 좁은 화면에 그런거 구겨넣어서 딱히 좋은점도 모르겠고 느려지기만 하는거 같아서 Aptana 기본 환경에 PHP 에디터만 추가해서 쓰는게 제일 좋은것 같음. 단축키도 일반적인 윈도우 어플들과는 좀 다른면이 있고 기본적으로 워드랩도 안되는 등의 자잘한 태클들이 많지만 그나마 이게 어디야..

Aptana Logo

사실 Aptana의 강점은 JS/RIA 개발과 디버깅에 매우 강하다는 거지만 그냥 firebug와 alert()이 익숙해요..;;

'컴퓨터 얘기 > 프로그래밍' 카테고리의 다른 글

iPhone 에서 OAuth 라이브러리 사용하기  (2) 2010/03/05
Read Me 플러그인  (3) 2007/12/07
드림위버와 이별하기  (5) 2007/11/28
MySQL Foreign Key 바보짓  (6) 2007/04/09
TinyMCE 플러그인 - WikiExporter  (5) 2007/02/07
멜론 앨범 커버 다운로더  (20) 2007/02/04

MySQL Foreign Key 바보짓

DROP TABLE IF EXISTS testChild;
DROP TABLE IF EXISTS testParent;

CREATE TABLE testParent (
    id INT NOT NULL,
    PRIMARY KEY(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE testChild (
    id INT NOT NULL,
    parentId INT DEFAULT NULL,
    PRIMARY KEY(id),
    KEY parentId(parentId),
    CONSTRAINT testFKey FOREIGN KEY(parentId) REFERENCES testParent(id)
        ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO testParent VALUES(1);
INSERT INTO testChild VALUES(1, 1);

ALTER TABLE testChild MODIFY parentId INT NOT NULL;

DELETE FROM testParent WHERE id = 1;

MySQL 5.0에서는 마지막 DELETE문을 실행할때 mysql이 crash 되고 4.1에서는 testChild 테이블에 (1, 0) 값이 남게 돼 foreign key constraint가 깨지게 된다. 아놔 이자식 때문에 반나절을 삽질했;;

'컴퓨터 얘기 > 프로그래밍' 카테고리의 다른 글

Read Me 플러그인  (3) 2007/12/07
드림위버와 이별하기  (5) 2007/11/28
MySQL Foreign Key 바보짓  (6) 2007/04/09
TinyMCE 플러그인 - WikiExporter  (5) 2007/02/07
멜론 앨범 커버 다운로더  (20) 2007/02/04
Crizin.HTTPRequest.php  (8) 2007/02/03

TinyMCE 플러그인 - WikiExporter

회사에서 생성되는 문서의 많은 부분은 Trac의 위키로 관리된다. 장점이 많지만 문서의 길이가 길어지기 시작하면 위키 코드만 보고는 편집하기 어려운 것도 사실이다. 좀 분량이 되는 문서를 Google Docs에서 만들었다가 위키로 옮길 일이 있어 예전에 만들다 말았던 위키도우미;;를 끄집어내 TinyMCE 플러그인으로 만들었는데 어지간히 복잡한 문서 말고는 그럭저럭 나와주는 것 같다. 덕분에 집에 일찍 갔다-_-

다운로드 : WikiExporter.1.0.zip (6.02KB)

그림에 보이는 것 처럼 원본은 Google Docs나 드림위버나 MS워드같은 HTML 편집이 가능한 곳에서 작성하고 TinyMCE 편집화면에 붙여넣은 후 왼쪽 위에 있는 빨간 W 버튼을 누르면 HTML 코드를 변환해준다. 문서가 지나치게 길면 컴퓨터가 폭발할 수도 있으니 주의..

TinyMCE를 다운로드 받아 플러그인을 설치해서 써도 되고 (어디 업로드 하지 않고 그냥 PC에서 바로 실행해도 된다) 귀찮은 사람은 이 쪽을 이용해도 된다.

'컴퓨터 얘기 > 프로그래밍' 카테고리의 다른 글

드림위버와 이별하기  (5) 2007/11/28
MySQL Foreign Key 바보짓  (6) 2007/04/09
TinyMCE 플러그인 - WikiExporter  (5) 2007/02/07
멜론 앨범 커버 다운로더  (20) 2007/02/04
Crizin.HTTPRequest.php  (8) 2007/02/03
preg 계열 함수들의 버그?  (10) 2006/08/21

멜론 앨범 커버 다운로더

앞선 Crizin.HTTPRequest.php의 활용 예.

D2 재생모습

D2에서는 각 MP3 파일마다 같은 이름을 가진 JPG 이미지를 넣어놓으면 노래를 재생할때 옆에 같이 보여주는데 멜론 인기곡 Top100 같은걸 다운받아 넣고 각 앨범 커버를 손으로 하나씩 넣어주자면 굉장한 노가다를 해줘야 한다. 이 과정을 간단히 줄여주는 스크립트가 바로 이 녀석.

다운로드 : melon.zip (2.11MB)

압축풀고 auto.bat(이 파일명 정말 좋아;;)를 실행하면 covers 디렉토리를 만들고 오늘의 차트 종합순위 Top100에 해당하는 앨범 커버를 다운로드 한다. 에픽 하이-17-Fan.jpg 같은 이름으로 만들어주기 때문에 대부분의 경우는 멜론에서 받은 DCF 파일이 들어있는 곳에 같이 넣어주기만 하면된다. 가끔씩 에픽 하이-17-Fan.jpg 처럼 트랙번호가 어긋나는 경우가 있는데 멜론 앨범정보가 이상하게 들어있어서 이건 어쩔 수 없음. 몇개 안되니 손으로 고쳐주자;; 또 타이푼-01-기다릴게....jpg 처럼 제목이 마침표로 끝나는 경우에는 D2에서 제대로 앨범 커버 인식을 못하는 것 같으니 DCF, JPG 양쪽 모두 ...을 제거해줘야 한다.

오늘의 Top100이 아니고 주간, 월간 차트의 곡을 받고싶거나 종합순위 말고 가요, 팝 등의 개별 장르 차트를 다운로드 하고 싶으면 src 디렉토리의 melon.php 파일을 메모장으로 열어 앞부분을 약간 수정해줘야 한다.

melon.php 수정화면

공장 출하값(..)은 오늘의 종합차트로 맞춰져있고 이걸 월간 클래식 차트로 바꾸고 싶다면 8번째줄 맨 앞에다 //를 넣어주고 10번째의 //를 제거하고 같은 방법으로 14번째줄에 //를 추가, 19번째줄의 //를 제거하면 된다.

php.exe도 포함돼있고 해서 거시기한 문제가 될 수도 있으니 다른곳으로의 펌/업로드는 삼가해주시기를..

'컴퓨터 얘기 > 프로그래밍' 카테고리의 다른 글

MySQL Foreign Key 바보짓  (6) 2007/04/09
TinyMCE 플러그인 - WikiExporter  (5) 2007/02/07
멜론 앨범 커버 다운로더  (20) 2007/02/04
Crizin.HTTPRequest.php  (8) 2007/02/03
preg 계열 함수들의 버그?  (10) 2006/08/21
IE 6.0의 버그들  (7) 2006/08/11

Crizin.HTTPRequest.php

예전에 웹브라우저를 에뮬레이트 하는 간단한 PHP 클래스를 만든적이 있었는데 회사에 들어온 뒤 파파챠님이 만드신 태터툴즈용 HTTPRequest 클래스에 감명을 받아;; 전체적인 모습을 그 것과 비슷하게 발전시켜왔다. 2년넘게 이걸로 다양한 짓거리들을 하며 써오고 있는데 마지막 버전업이 작년 여름인걸 보니 이제 될건 다 되겠다 싶어 공개. Snoopy같은 라이브러리와 많이 비슷한데 필요한 기능들을 집어넣다보니 꽤 다르게 됐다. 이걸 가지고 할 수 있는 일은 A 게시판을 RSS로 만들어 구독한다던가 B 갤러리에 새 사진이 등록되면 하드에 저장한다던가 브라우저로는 접근하기 어려운 C 사이트의 뒷구멍으로 뭔가를 날리는 등등의 다양한 노가다성 작업이 가능하다.

다운로드

Download from GoogleCode

Simple tutorial

<?
    require 'Crizin.HTTPRequest.php';

    // Create instance
    $h = new HTTPRequest('www.foo.com');
    // Turn on debug mode (request/response streams will be print)
    $h->debug(true);
    // Setting 'PATH'
    $h->setPath('/');
    // Request by GET method
    $h->send();
    // Get responsed informations
    $responseText = $h->responseText;
    $contentType = $h->getResponseHeader('Content-Type');

    // Let's try to another host into 8080 port
    $h->open('www.bar.com', 8080);
    // Path and GET parameter string
    $h->setPath('/accept.php?mode=login&and=more');
    // Send around proxy server
    $h->setProxy('www.proxy.com', 8888);
    // Modify 'User-Agent' header
    $h->setRequestHeader('User-Agent', 'Gozilla/1.0');
    // Import from cookie string
    $h->importCookie('COOK1=foo; COOK2=bar;');
    // Set cookie
    $h->setCookie('cook', 'something');
    // Request by POST method
    $h->send('param1=value1&param2=value2');
    // Get cookie
    $sessionId = $h->getCookie('PHPSESSID');

    // Download image
    $h->setPath('/images/logo.gif');
    // Login with apache authorization
    $h->authorization('myId', 'myPassword');
    // Hide 'User-Agent' header
    $h->removeRequestHeader('User-Agent');
    // Response content will be saved in './save'
    $h->saveToFile('./save');

    // Upload some files
    $h->setPath('/write.php');
    // <input type="file" name="image" value="/files/blah.gif"/> and rename to 'myImage.gif'
    $h->attachFile('image', './files/blah.gif', 'myImage.gif');
    // Request
    $h->send();

    // Test some text exists in $responseText or not
    $result = $h->existText('OK') ? 'Succeed' : 'Failed';
    // Get all text fragments was surrounded by '<td>' and '</td>' (array will be return)
    $result = $h->getAllTextFragments('<td>', '</td>');
    // Get 5th text only (string will be return)
    $result = $h->getTextFragment('<td>', '</td>', 5);
?>

'컴퓨터 얘기 > 프로그래밍' 카테고리의 다른 글

TinyMCE 플러그인 - WikiExporter  (5) 2007/02/07
멜론 앨범 커버 다운로더  (20) 2007/02/04
Crizin.HTTPRequest.php  (8) 2007/02/03
preg 계열 함수들의 버그?  (10) 2006/08/21
IE 6.0의 버그들  (7) 2006/08/11
태터툴즈 1.0.5 플러그인  (58) 2006/05/09

preg 계열 함수들의 버그?

preg_match('/(.)*/', str_repeat('x', 20000), $matches);

PHP에서 위 명령을 실행하면 $matches 변수에 아래와 같은 값이 들어가야 정상이지만,

array(2) {
   [0]=>
   string(20000) "xx...xx"
   [1]=>
   string(1) "x"
}

Segmentation fault를 내고 죽어버리는 경우가 있다. 이유는 아직 이해불가; 20000번의 매치 과정중 두번째 원소에 계속 x를 저장하는 과정에서 메모리가 빵꾸나는게 아닐까 하는 생각이 들지만 캡쳐기능이 없는 괄호 (?:.)*를 사용해봐도 역시 죽어버린다. ereg 계열 함수는 제대로 실행이 되는걸 보면 preg 함수가 삽질하고 있는게 맞는 것 같다. preg_replace(), preg_match_all() 등 모든 함수에서 동일한 결과가 나오며 PHP 4.4.1, 5.1.4에서 이런 증상을 보였다.

좀 복잡하다 싶은 정규식은 극한 상황의 테스트를 꼭 해볼 것;

'컴퓨터 얘기 > 프로그래밍' 카테고리의 다른 글

멜론 앨범 커버 다운로더  (20) 2007/02/04
Crizin.HTTPRequest.php  (8) 2007/02/03
preg 계열 함수들의 버그?  (10) 2006/08/21
IE 6.0의 버그들  (7) 2006/08/11
태터툴즈 1.0.5 플러그인  (58) 2006/05/09
태터툴즈 방문자 그래프 플러그인  (9) 2006/03/22

IE 6.0의 버그들

1. letter-spacing 문제

자간을 줄이는 CSS 속성인 letter-spacing을 -1px 정도로 주면 글자가 다닥다닥 붙어 정돈되고 아기자기한 느낌을 준다. 이 속성을 썼을때 일어날 수 있는 문제중 잘 알려진 것 중 하나는 특정한 코드와 섞여있을때 br 태그를 두번 입력해야 줄바꿈이 되는 문제가 있다. 그리고 어제 gendoh님이 발견한 새로운 버그는 꽤 재밌다.

<html>
   <head>
       <style type="text/css">
           body { letter-spacing: -1px; }
       </style>
   </head>
   <body>
       <br/><br/><br/><br/><br/><br/><br/>
       <br/><br/><br/><br/><br/><br/><br/>
       <br/><br/><br/><br/><br/><br/><br/>
       <br/><br/><br/><br/><br/><br/><br/>
       <br/><br/><br/><br/><br/><br/><br/>
       <div style="float: left">A</div>B
   </body>
</html>

View example

위에 줄바꿈이 주루룩 있으면 저 코드에서 B가 A를 잡아먹어버린다. div 태그 안에 이미지나 기타 등등 아무리 거대한놈이 있어도 화면에는 표시되지 않는다. 더 재밌는건 위에 br 태그의 개수를 늘이거나 줄이면 이 버그는 사라진다. tistory 새 스킨 QA 과정에서 우연히도 엔터를 35번 눌러 버그를 발견한 gendoh님께 박수;

2. 잘못된 ul 태그 렌더링 문제

이건 HTML이 잘못된 문법으로 작성된 거지만 IE의 처리가 깔끔하지 못했다. 역시 tistory 새 스킨에서 ul/li 태그로 구성한 코멘트 부분이 스크롤 할때마다 배경색이 깨져버리는 문제가 있었는데 처음엔 li 태그의 padding 때문인줄 알았지만 나중에 보니 근본적인 원인은 잘못 들어간 a 태그때문에 생긴 문제였다. (어제는 li 태그의 아래쪽 padding 값을 0으로 했더니 문제가 사라져서 그냥 넘어갔음;)

<html>
   <head>
       <style type="text/css">
           li { padding-top: 8px; background-color: #aaa; }
       </style>
   </head>
   <body>
       <ul>
           <a id="anchorHere"></a>
           <li><div>-_-</div></li>
           <a id="anchorHere"></a>
           <li><div>-_-</div></li>
           ...
           <a id="anchorHere"></a>
           <li><div>-_-</div></li>
       </ul>
   </body>
</html>

View example

위 예제 페이지를 열어서 스크롤바를 잡고 위아래로 천천히 이동해보면 li 태그의 배경색이 찢어지는 현상을 볼 수 있다. 이 현상은 브라우저 크기를 작게 할 수록, 스크롤 속도를 느리게 할 수록 잘 볼 수 있다.

3. design mode scrolling 문제

태터툴즈 위지윅 에디터에서 아래쪽 커서키를 계속 누르면 화면 끝에서 더이상 스크롤 되지 않는 버그가 있었다. 이렇게 브라우저가 후져서 생기는 버그는 여러가지 원인이 누적돼 하나의 현상으로 터져버리는 경우가 많은데 이 경우는 에디터 영역의 줄간격을 150%에서 163%로 바꿔서 해결했다. 비슷한 상황을 간단히 재현해보면 아래와같은 경우도 있다.

<html>
   <head>
       <style type="text/css">
           div { float: left; width: 200px; }
           iframe { width: 100%; }
       </style>
       <script type="text/javascript">
           window.onload = function() {
               var document1 = document.getElementById("Frame1").contentWindow.document;
               var document2 = document.getElementById("Frame2").contentWindow.document;
               document1.designMode = document2.designMode = "on";
               var html = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html><head><style type="text/css">body { font: 12px/1.5 Dotum, Sans-serif; }<\/style><\/head><body>1<br/>2<br/>3<br/>4<br/>5<br/>6<br/>7<br/>8<br/>9<br/>10<br/>11<br/>12<br/>13<br/>14<br/>15<br/>16<br/>17<br/>18<br/>19<br/>20<br/><\/body><\/html>';
               document1.open("text/html", "replace");
               document1.write(html);
               document1.close();
               document2.open("text/html", "replace");
               document2.write(html);
               document2.close();
           }
       </script>
   </head>
   <body>
       <div>
           <iframe id="Frame1"></iframe>
       </div>
       <div>
           <iframe id="Frame2"></iframe>
           <table style="margin-top: 3px"></table>
       </div>
   </body>
</html>

View example

예제에 보이는 두개의 iframe중 첫번째 프레임은 정상이고, 두번째 프레임은 아래 방향키를 계속 눌러보면 스크롤되지 않고 화면 끝에서 첫번째 줄로 커서가 점프한다-_- 해결하려면 iframe 아래에 있는 테이블의 위쪽 마진을 없애거나 줄간격을 바꾸거나 iframe document의 DOCTYPE을 제거하는 등의 다양한 방법이 있다.

4. IE를 다운시키는 코드

열기만 해도 IE가 다운되는 HTML 코드가 있다. 내가 알고 있는건 아래 두가지인데,

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
   <body>
       <table style="table-layout: fixed">
       <col width="10"></col>
   </body>
</html>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
   <body>
       <table>
       <tr>
           <td>
               <table style="table-layout: fixed">
               <col width="10"></col>
               <col width="10"></col>
               </table>
           </td>
       </tr>
       </table>
   </body>
</html>

예전에 tattertools.com 메인 페이지는 두번째 코드가 포함돼 있었다. 가운데 있는 테이블에 내용이 반복해서 들어가게 되는데 어느날 DB가 살짝 맛이 가서 <tr>...</tr> 부분이 쏙 빠져버려 위와 같은 모습이 돼버렸다. 당연히 tattertools.com을 방문하는 대부분의 사람은 브라우저가 죽어버리는 경험을 할 수밖에 없었다; 궁금하신 분은 작업중이던거 다 저장하고 아래의 링크를 눌러보면 된다.

View example1 View example2 (주의 : 브라우저가 다운될 수 있습니다)

'컴퓨터 얘기 > 프로그래밍' 카테고리의 다른 글

Crizin.HTTPRequest.php  (8) 2007/02/03
preg 계열 함수들의 버그?  (10) 2006/08/21
IE 6.0의 버그들  (7) 2006/08/11
태터툴즈 1.0.5 플러그인  (58) 2006/05/09
태터툴즈 방문자 그래프 플러그인  (9) 2006/03/22
태터툴즈에 FTP로 첨부파일 올리기  (11) 2005/10/04
태그 : Tip

태터툴즈 1.0.5 플러그인

태터툴즈 1.0.5 릴리즈에 맞추어 만든 플러그인 4종세트.. 당연히 1.0.5 이상에서만 동작하며 각 플러그인들의 라이선스는 GPL에 따르니 더 좋게 고쳐서 나눠쓰세요..;

로봇의 방문횟수 제외 [Download - ExcludeRobotsCounter.zip]

기능
많이 알려진 로봇의 이름을 미리 입력해서 로봇이 방문했을때는 방문자 카운터를 증가시키지 않는다.
설명
플러그인 관리자 화면에서 플러그인을 활성화 시키면 동작한다. 봇의 이름을 추가하거나 삭제할때는 index.php 파일을 열어 $robots 배열에 봇의 이름을 편집해주면 된다. 추후에 User-agent 필터링 기능이 추가되기 전까지 임시로 사용되는 플러그인.

피드버너 리다이렉터 [Download - FeedBurnerRedirector.zip]

기능
태터툴즈의 RSS 주소로 접속하면 피드버너의 피드 주소로 이동시켜준다. 스킨의 [##_rss_url_##] 치환자도 피드버너의 URL로 바뀐다.
설명
사용하는 블로그 식별자가 crizin 이라면 http://feeds.feedburner.com/crizin 주소로 이동된다. 블로그 식별자와 피드버너 ID가 다른 경우에는 index.php 파일 10번째줄의 "http://feeds.feedburner.com/{$blog['name']}" 부분을 "http://feeds.feedburner.com/xxxxxx" 같이 변경해줘야 한다. 피드버너 설정에서 Original Feed 주소는 http://crizin.net/rss 같이 원래 RSS 주소를 입력해두면 된다.

전체피드 읽어오기 [Download - GetEntireFeed.zip]

기능
네이버의 모든 블로그, 이글루스의 블로그중 피드 부분공개를 선택한 블로그에 대해 본문 전체를 보여준다.
설명
플러그인을 활성화 시키면 피드가 업데이트 될때마다 직접 블로그에 접속해 본문을 읽어와 RSS의 본문 대신 저장하게 된다. 따라서 피드 업데이트 속도가 느려질 수 있으며 특이한 스킨을 사용하는 이글루스 블로그에 대해서는 본문을 제대로 읽어오지 못할 가능성도 있다.
주의
부분공개된 피드의 전문을 강제로 읽어와 리더에 저장하는건 블로거의 의도에 반하는 행동이 될 수 있다. 개인적인 편의가 아닌 다수에게 서비스를 제공하는 블로그에서 이 플러그인을 사용하는건 문제의 소지가 될 수 있음에 주의할 것.
변경내역
1.0.1 - 네이버의 글에서 이미지에 달려있는 onload 이벤트를 제거해서 스크립트 오류가 뜨지 않게 함
1.0.2 - 파란의 RSS도 지원 (포스트 하나 가져오려면 두번 접속을 해야해서 매우 느림)
1.0.3 - 네이버 블로그 출력부분 변경사항 반영
1.0.4 - 파란 블로그 출력부분 변경사항 반영
1.0.5 - 네이버 블로그 출력부분 변경사항 반영, 이글루스 포스트는 무조건 읽어오도록 수정

리퍼러 로그 정리 [Download - RefererURLBeautifier.zip]

기능
통계보기 » 리퍼러 통계를 봅니다 메뉴에서 리퍼러 로그를 읽기 쉽게 바꿔주고 검색어가 포함된 경우 검색어를 눈에 잘 띄게 표시해 준다.
설명
리퍼러를 저장하는 공간(255bytes)의 제약으로 인해 매우 긴 URL의 경우 한글이 깨지는 등의 문제가 있을 수 있다. 그리고 index.php 파일의 15번째줄 맨 앞의 //를 제거하면 각 도메인의 favicon을 불러다 표시해준다.
변경내역
1.0.1 - Eolin.com 검색어 표시가 안되는 문제 수정
1.0.2 - Baidu.com 검색어 표시가 안되는 문제 수정
1.0.3 - %uXXXX 형식의 문자 해석해서 보여주도록 수정
1.0.4 - http://images.google.co.kr 등에서 유입되는 검색어가 제대로 추출되지 않는 문제 수정

태터툴즈 방문자 그래프 플러그인

예전에 만들었던 태터툴즈 클래식용 그래프 프로그램을 태터툴즈 1.0.2 이상에서 쓸 수 있는 플러그인으로 제작..

대충 이런 모양으로 출력된다. 사용법은,

  1. 플러그인을 plugins 디렉토리에 설치 (그리고 환경설정에서 활성화 시켜줌)
  2. VisitorStatisticsGraph 디렉토리의 퍼미션을 707 정도로 조정 (chmod 707 VisitorStatisticsGraph)
    (그래프가 생성되지 않고 자꾸 엑박으로 뜬다면 이부분을 의심해봐야함)
  3. 플러그인의 index.php 파일을 열어서 5째줄부터 나오는 그래프 설정을 원하는 모양대로 맞춘다
  4. 스킨의 적당한 곳에 [##_VisitorStatistics_##] 이라는 태그를 삽입한다

그래프는 하루에 한번만 갱신되므로 설정값을 변경한 후에는 graph.png 파일을 삭제하고 다시 블로그 페이지를 열어서 graph.png 파일을 생성해야 한다.

태터툴즈에 FTP로 첨부파일 올리기

태터툴즈 포럼에 뎅엽이님 질문을 보고 하나쯤 있으면 좋겠다는 생각이 들어 만들었다. 원래는 Flash8에 추가된 업로드 기능으로 폼나게 만들어볼 생각이었는데 거친마루님의 예제를 한참 보고있으니 머리위에 OTL이라는 말풍선이 뜨면서 기운이 확 빠져버리는 현상이;; 그리하여 결국 FTP로 업로드한 파일을 태터툴즈에 붙여주는 원시적인 방식을 택하게 됐음.

upload.php

Version 2006.01.04.01

사용법,

  1. 위의 파일을 내려받아 태터툴즈 홈 디렉토리에 올려놓는다.
  2. 태터툴즈 홈 디렉토리에 upload 라는 디렉토리를 만들고 FTP로 사진이나 기타 파일을 올려놓는다.
    (upload가 아닌 다른 디렉토리 이름을 쓰고싶으면 upload.php 파일의 4번째줄을 수정한다)
  3. 1번에서 업로드한 upload.php 파일을 호출하면 글목록과 업로드한 파일 목록이 보인다 (관리자 로그인 필요)
  4. 파일을 첨부할 포스트를 선택한다. 새로운 포스트로 붙이고 싶으면 (새 포스트)를 선택하면 됨.
  5. 나열된 파일 목록중에서 첨부를 원하지 않는건 체크를 해제한다.
  6. 등록 버튼을 누르면 잠시 시간이 걸린 후 결과가 표시된다.
  7. 각각의 파일 끝에 (복사 성공)이라는 메세지가 뜨면 성공인데 실패라고 뜨면.. 이 포스트에 답글을 달아 도움을 요청한다;;

파일이 이동되는게 아니고 복사된다는 점에 주의. 아직 충분한 테스트를 거치지 못해서 삭제하는 코드를 넣기가 겁나는 관계로..;; 일단 등록이 끝난 파일은 수동으로 지워줘야 한다.

태그 : 태터툴즈

자바스크립트에서 문자열을 합치는 방법

어제 워크샵에서 배운 것들을 이것 저것 해보는 중인데 그 중 StringBuffer의 성능에 대해 간단히 벤치마킹 해본 결과를 적어본다. 진작에 좀 알았으면 좋았을 것을..;

자바스크립트에서 두 문자열을 하나로 합치고 싶을때는 + 연산자로 간단히 합칠 수 있다. 다른 언어에서도 마찬가지지만 좀 저수준에서 바라보면 문자열을 합치는 작업은 앞쪽 문자열의 끝부분을 찾아서 그 뒤에 뒤쪽 문자열을 붙이는 방법이기 때문에 앞쪽 문자열이 길수록 작업시간이 늘어난다. 그래서 거대한 양의 HTML 코드를 동적으로 생성해 + 연산자로 이어붙여 innerHTML 메소드로 넣어줄때는 문자열이 길어질 수록 길이의 제곱에 비례해 시간이 늘어나는 걸 볼 수 있다.

자바의 경우는 이 문제를 StringBuffer라는 객체를 사용해 해결한다. 일정 공간의 버퍼를 만들고 여기에 문자열을 추가하면서 버퍼가 모자라면 지금 할당된 버퍼의 용량을 두배로 늘려 사용하는 단순한 방법인데 속도가 상당히 향상된다.

자바스크립트에서는 메모리를 직접 다루는게 불가능하기 때문에 이런 방법은 쓰기 힘들고, 추가할 문자열을 실제로 이어붙이는게 아니라 배열에 임시로 넣어두었다가 필요할때 합쳐서 쓰는 방법을 사용한다. 배열에 문자열을 집어넣는건 문자열의 길이와 상관없이 항상 일정한 시간이 걸리기 때문에 최종적으로 문자열을 하나로 합치는 시간에서만 문자열의 길이에 비례한 시간이 소요된다.

Example. http://crizin.net/work/demo/stringBufferExample.html

prototype을 선언해서 좀 더 우아하게 쓸 수도 있다.

Example. http://crizin.net/work/demo/stringBufferPrototypeExample.html (참고 : Java Script String Buffer)

아무튼 저런식으로 문자열을 다루면 극한 상황일수록 많은 시간을 줄일 수 있게된다. IE의 경우에는 대략 몇십배씩 차이가 나는데 파이어폭스나 오페라 같은 경우는 두 방법의 차이가 거의 없다. 아마 내부적으로 + 연산자를 StringBuffer로 처리하는게 아닌가 추측됨. (오페라의 경우에는 최적화가 잘 돼 있는지 오히려 + 연산자가 더 빠르다)

Demo : http://crizin.net/work/demo/stringBenchmark.html

그래서 결론은 IE7이 빨리 나오길 바란다는 것으로 마무리;;

태터툴즈 + BBClone의 10원짜리 팁

Trackback to :: 강력한 접속통계 프로그램 BBClone

예전부터 쓰려고 했던건데 잊고있다 올블로그에서 한스님의 포스트를 보고 생각난김에 간단히 기록한다.

BBClone은 방문한 페이지에 각각 ID를 부여해서 페이지별 순위를 매길 수 있는데 태터툴즈에서라면 각 포스트별 순위를 매기는 용도로 쓸 수 있다. 일반적인 index.php 맨 처음부분에 코드를 삽입하는 경우라면 아래처럼 넣으면 된다.

switch($md)
{
    case "rss": $bbclone_id = "RSS Paper"; break;
    case "guest": $bbclone_id = "Guestbook"; break;
    case "local": $bbclone_id = "Locations"; break;
    case "keyword": $bbclone_id = "Guestbook"; break;
    default: $bbclone_id = $pl ? "POST #$pl" : "Blog Main";
}

define("_BBC_PAGE_NAME", $bbclone_id);
define("_BBCLONE_DIR", "bbclone/");
define("COUNTER", _BBCLONE_DIR."mark_page.php");

if
(is_readable(COUNTER))
    include_once(COUNTER);

예제는 본인의 BBClone 페이지로..;

태터툴즈 답글 + 기타등등을 RSS로

Trackback to :: 블로그에 코멘트 남기면 쪽지 날라오게 하기

Miranda-IM에 입문하면서 이것저것 만져보는 중인데.. 이것저것 다 마음에 들지만 메신저 주제에 옵션이 이렇게 복잡하리라고는 상상도 못했다 orz;; 그만큼 강력하다는 얘기겠지만서도.. 나름대로 처음보는 프로그램에 대한 적응이 빠르다고 생각하는데 이녀석은 시간좀 걸릴 듯 싶다.

아무튼 예전부터 탐냈던 최근 답글 목록을 RSS로 만들어 Miranda로 알림받는 것도 해봤는데 최근버전의 RSSNews 플러그인에 Store only unread news 옵션이 없어져버려 살짝 문제가 됐지만 (다시 보니까 Maximum displayed items 옵션에 1을 넣으면 알려줄 답글이 여러개일 경우에 하나 알려주고 또 알려주고 하는식으로 알림이 온다. 이렇게 되면 위 옵션은 굳이 없어도 될 듯) (그냥 기본값 그대로 0을 넣어두면 답글 하나에 메세지 하나씩 잘 온다) 일단 편하고 좋다. 예전에 골빈해커님이 만드신 패치를 약간 변형해서 답글, 트랙백, 방명록, 방명록 답글을 시간순서대로 보여주는 스크립트를 만들어서 쓰고있다.

rss_notify.php

Version 2006.01.01.01

..이제 답글만 많이 달리면 된다;

태그 : RSS, 태터툴즈

Konfabulator Widget 만들기

뒤늦게 Konfabulator를 받아서 위젯들을 들었다 놨다 하면서 놀던중에 위젯이 자바스크립트로 만들어졌다는 충격적인 사실을 알아냈다. 자바스크립트라면 덤벼볼만 하지. Konfabulator Workshop 페이지에 가서 튜토리얼 문서를 받아 살펴보다가 몇번 좌절한 끝에 우선 남이 만들어놓은거 한번 뜯어보는 걸로 방향을 바꿨다. 위젯 갤러리를 훑어보다가 RSS를 읽어다 표시해주는게 왠지 만만해보여서 The Apple Blog RSS라는 놈을 잡아다 분석해봤더니 생각보다 심플! 위젯 내부는 XML 파일에서 화면을 꾸미고 자바스크립트를 호출해 사용하는 기묘한 구조로 이루어져 있었다. 테스트용으로 배경이미지 하나 달랑 깔아놓고 블로그의 최근 답글 5개를 불러다 표시해주는 녀석을 만들었다. (거의 copy & paste로 만든거긴 하지만;;)

태터툴즈 답글 위젯 실행화면

만들고 보니까 크기가 너무 크다 -_- 기능은 오로지 1분에 한번씩 답글 XML 파일을 불러다 뿌려주는 것 밖에 없다. 위에 첨부한 rss_replies.php 파일을 태터툴즈 메인에 올려놓고 위젯을 실행한 다음 Preference에 들어가 자신의 rss_replies.php 파일 URL을 적어줘야 한다. (기본값은 내 블로그가 들어가 있음;;) 그리고 호스팅 서버에서 iconv 함수 사용이 가능해야 한다. 글꼴은 굴림으로 했더니 영 보기 불편해서 HY견고딕으로 바꿔버렸다. 오피스던가 한글이던가 설치하면 같이 깔리는거 같던데.. 아무튼 웬만한 컴퓨터엔 다 있을 것으로 간주하고;; (HY견고딕, 중고딕 같은건 윈도우에 기본으로 좀 넣어줬으면 좋겠다)

위젯 만드는거 꽤 재밌어서 당분간은 이녀석으로 심심하지 않을 것 같다;

태터툴즈 답글 삭제부분 수정

태터툴즈 0.96 정식버전에만 해당하는 내용임

어쩌다보니 최근엔 계속 태터툴즈 관련 포스팅이다. 아무튼;; 0.96 정식버전에 추가된 기능중의 하이라이트라고 할 수 있는 답글에 답글달기 기능 중에 의도한 것과 살짝 다르게 동작해서 당황하게 되는 부분이 하나 있는데, 하위 답글이 달린 상위 답글을 삭제했을때의 경우다. 상위 답글이 삭제되면서 하위 답글들은 최근 답글 목록 외에서는 영영 볼 수 없는 미아가 돼버리고 마는데 이걸 방지하려면 약간의 수정이 필요하다.

칼을 대야할 부분은 del_exe.php 파일의 34 ~ 43번째 줄이다. (아래 표시된 부분)

put_query("delete from t3_".$dbid."_reply where no = '$num'");
set_rp_cnt($pnum);
?>
<script type="text/javascript">
    alert('지정하신 글이 삭제되었습니다t');
    opener.exe_frame.location.href='add_exe.php?md=rp&num=<?=$pnum?>&d_target=post_<?=$pnum?>';
    window.close();
</script>
<?
exit;

위의 부분을 일단 아래와 같이 고쳐놓은 뒤에,

list ($is_parent) = mysql_fetch_array(mysql_query("select count(*) from t3_${dbid}_reply where rno = '$num'"));

if($is_parent)
{
    /* 뭔가 삽입될 곳 */
}
else
{
    put_query("delete from t3_".$dbid."_reply where no = '$num'");
    set_rp_cnt($pnum);
    ?>
    <script type="text/javascript">
        alert('지정하신 글이 삭제되었습니다t');
        opener.exe_frame.location.href='add_exe.php?md=rp&num=<?=$pnum?>&d_target=post_<?=$pnum?>';
        window.close();
    </script>
    <?
    exit;
}

/* 뭔가 삽입될 곳 */ 이라고 표시된 곳에 어떻게 처리할건지에 따르는 코드를 넣어주면 된다. 답글 삭제시에 하위 답글을 어떻게 처리할 것인가는 기호에따라 몇가지 방법이 있을 수 있는데 대략 3가지 정도 추려보면,

  1. 상위 답글을 아예 못지우게 하는 방법. 방문자의 삭제 권리를 무시하는 방법이므로 사전에 낙장불입 시스템임을 알려둘 필요가 있다.
    ?>
    <script type="text/javascript">
        alert('하위 답글이 달려있어서 지울 수 없습니다t');
        window.close();
    </script>

    <?
    exit;
  2. 상위 답글의 이름, 홈페이지, IP, 본문만 날려버리는 방법. 일단 리플 개수가 줄어들지 않아 좋다 -_-
    put_query("update t3_${dbid}_reply set name='Anonymous', homepage='', body='(삭제된 답글입니다)', password='', ip='0.0.0.0' where no = '$num'");
    ?>
    <script type="text/javascript">
        alert('하위 답글이 달려있어서 내용만 삭제했습니다t');
        opener.exe_frame.location.href='add_exe.php?md=rp&num=<?=$pnum?>&d_target=post_<?=$pnum?>';
        window.close();
    </script>

    <?
    exit;
  3. 하위 답글까지 몽땅 삭제하는 방법. 화끈한 만큼 운영에 주의가 필요하다.
    put_query("delete from t3_${dbid}_reply where no = '$num' or rno = '$num'");
    set_rp_cnt($pnum);
    ?>
    <script type="text/javascript">
        alert('지정하신 답글과 관련 답글이 모두 삭제되었습니다t');
        opener.exe_frame.location.href='add_exe.php?md=rp&num=<?=$pnum?>&d_target=post_<?=$pnum?>';
        window.close();
    </script>

    <?
    exit;

이렇게 3개의 방법중 원하는 방법에 해당하는 코드를 /* 뭔가 삽입될 곳 */ 부분에 넣어주면 된다.

이 블로그는 두번째 방법을 쓰고있다. 어떤 방법이든 이렇게 수정해두지 않으면 쓰레기 데이터가 쌓여서 DB의 일관성에도 문제가 있고 Staticker 같은 통계프로그램에서도 잘못된 결과가 나올 수 있으니 가급적 수정해주는쪽을 추천.

태그 : 태터툴즈

태터툴즈 0.96 위치로그 업데이터

태터툴즈 0.96RC에서 입력된 위치정보는 일단 기본적으로는 태터센터 지역별 목록에 표시되지 않는 모양이다. 이럴땐 싱크를 다시 시켜줘야 목록에 표시되는데 각각의 포스트 수정화면에 들어가 REFLECT 버튼을 한번씩 눌러서 다시 싱크시켜주면 된다. (0.96 정식버전 부터는 싱크된 포스트일경우 REFLECT만 해도 수정된 내용으로 다시 싱크된다) 일일히 작업하기는 귀찮을땐 아래의 스크립트를 사용하면 간편하게 할 수 있다.

위의 파일을 ftp로 태터툴즈 메인 디렉토리에 올려놓고 웹브라우저에 http://yourdomain.com/location.php 이런식으로 입력해서 실행되는 화면을 지켜보기만 하면된다. 일단 위치정보가 삽입된 포스트중 이미 싱크된 포스트의 목록이 나열되고 각각의 포스트를 싱크시켜 성공, 실패 여부를 표시하게 된다. 모든 포스트 제목 뒤에 (성공) 이라고 표시되면 작업 끝. 실패 메세지가 나온다거나 반응이 없거나 하는 경우에는 일일히 REFLECT 버튼을 눌러주거나 SYNC 해제 후 재 SYNC 작업을 하는 수밖에 없다.

확실히 위치로그 등록해두니까 찾아오는 사람이 꽤 된다;; 지역별로 분류해서 보니까 메타사이트에서 시간순으로 보는 것과는 다른 재미도 있고.. 아직은 495개의 포스트 뿐인데 앞으로 글이 많이 늘어났으면 좋겠다.

이번껀 좀 많은 사람들이 봤으면 하는 바람이 있어서 올블로그 추천글로 등록함

태그 : 태터툴즈

태터툴즈 0.96용 노가다 유틸

드디어 기다리던 답글에 답글달기 기능이 추가됐다. 스킨을 고치고 스타일을 수정하는 과정에 예제가 필요해서 DB를 몇개 수정했는데 게시물이 280개 정도 되는 수준이라 이거 그냥 전부다 수정해버릴까? 하는 생각이 들어 노가다 작업에 필요한 유틸을 만들었다.

reply_helper.zip

주의 : 데이터 백업은 필수!!

DB를 직접 건드리는 민감한 물건이니 정신 바짝 차리고 해야함;; 무조건 데이터 백업후에 몇개 해보고 잘 된다 싶으면 계속 진행하고 이상하게 나오거나 답글이 사라져버리면 즉시 복구해야한다.

  1. 태터툴즈 메인 디렉토리에 올려놓고 reply.php 파일을 호출한다.
  2. 가장 최근의 포스트에 달린 답글이 표시된다. 첫번째 게시물에 답글이 없으면 실행 & 다음 게시물로 버튼을 눌러 답글달린 포스트가 나올때까지 넘어간다. (단축키 ALT-S)
  3. 답글이 쭉 나오면 작업을 시작한다. 방법은 먼저 부모글을 클릭하고, 그에 해당하는 자식 글을 클릭한다. (순서에 주의) 하나의 부모글에 여러개의 답글이 있을때도 부모글 클릭, 자식글 클릭을 반복하면 된다.
  4. 관계 설정이 끝나면 실행 & 다음 게시물로 버튼을 눌러 다음 게시물로 이동해 작업을 계속한다.
  5. 클릭을 잘못해서 취소하고 싶으면 F5키를 눌러서 새로고침한 다음에 다시 하면 된다.

다시한번 강조하지만 반드시 백업후 작업할 것 급조해서 이 블로그에만 적용한뒤 올려놓은거라 다른 곳에서는 이상동작을 하지 않는다는 보장이 없다.

덧. 0.96RC 쓰면서 입력해 놓은 글들이 태터툴즈 홈 지역별 분류 목록에 보이지 않는다면 해당 포스트의 SYNC를 한번 풀었다 다시 걸어주거나 게시물 편집으로 들어가서 위치 입력 옆의 SET 버튼을 한번 눌러주면 업데이트 된다.

덧. 아참 파일명이 reply.php, reply_exec.php 인데 태터툴즈에 원래 들어있는 reply_exe.php 파일과 혼동하지 않도록 주의. (아까 작업 끝내고 지운다고 저것까지 지워버리는 바보짓을 해서..;;)

태그 : 태터툴즈

태터툴즈용 간단한 통계 그래프

그래프 프로그램 데모 화면

최근 n일 동안의 데이터를 뽑아 출력해 그래프를 그려준다. 기존에 있는 것도 많지만 매일매일의 그래프가 아닌 증권차트의 n일 평균 이동선을 보고싶어서 삽질을 거듭해 완성. 오늘 기준으로 최근 두달간 5일 이동평균선의 추세를 보니 꾸준히 상승중. 지금이야말로 매입 찬스!;; 제일 높았던 기록은 올블로그 알찬글 올랐을때고 제일 낮았을때는 구글봇때문에 트래픽 초과됐던 날이다.

저 아래 graph.php 파일을 받아서 태터툴즈가 설치된 디렉토리에 올려놓고 파일을 열어서 변수들을 수정하면 된다.

num
불러올 카운터의 개수. 한달치를 불러오고 싶으면 30으로 수정.
width, height
각각 그래프의 너비, 높이.
trend
위 그래프에서 빨간 선으로 표시된 추세선의 기준값. 5라고 넣으면 그래프의 한 점의 값은 지난 5일간의 평균을 의미한다. 0을 집어넣으면 표시하지 않음.
grid
얼룩무늬의 폭을 지정하는건데 단위는 1일. num 값에 따라 유동적으로 변한다.
color_*
주석에 표시된대로 각각 배경, 무늬, 그래프의 색을 지정한다. 빨간색이면 0xff0000 이렇게 넣어주면 됨.

불러올때는 <img src="graph.php" width="175" height="95" alt="통계 그래프"/> 같은 식으로 호출하면 된다. 이렇게 되면 graph.png 파일이 만들어져 표시되게 되는데 이 파일은 하루에 한번만 만들어지기 때문에 최초에 graph.php 파일을 실행하면 변수를 바꿔서 또 실행해도 graph.png 파일이 업데이트 되지 않는다. 이럴땐 http://yourdomain.com/tt/graph.php?force=1 이렇게 실행해주면 강제로 graph.png 파일을 업데이트 한다. (참고로 저렇게 실행한 상태에서 새로고침을 누르면 graph.png 파일만 새로고침 되기 때문에 graph.php 파일은 호출되지 않는다. 그래서 변수를 수정하고 바뀐 내용을 확인할때는 항상 위에 적힌 URL처럼 PHP 파일을 직접 호출해줘야 함. 또 참고로 새로고침해도 잘 업데이트가 안되면 http://yourdomain.com/tt/graph.php?force=1&asdfasdf 이렇게 URL 뒤에 & + 의미없는 문자를 추가해 입력하면 확실히 새로고침 된다)

좀 그럴듯 하게 만들어서 배포하고 싶은데 이정도에 만족해버려서 더이상은 포기;

graph.php

Version 2005.08.16.01

실용예제로 배우는 웹표준

실용예제로 배우는 웹 표준 표지

어제 주문한 책이 벌써 도착해서 열심히 읽고있다. 그동안엔 초보자가 XHTML+CSS 기반의 코드에 입문하려고 해도 단편적인 팁만 존재하고 차근차근 읽어볼만한 자료가 거의 없다시피 했는데 이 책으로 갈증을 시원하게 풀어줄 수 있을 것 같다. 기존에 코딩을 해봤던 사람들이 읽기 적합한 정도의 수준인데 그동안 HTML 태그의 편식을 해왔거나 CSS를 글자꾸미기 정도에만 사용해왔던 사람이라면 이 책을 접하기 전에 XHTML 태그들의 사용법과 CSS 속성들을 대충이라도 한번 읽어본 후에 접해야 혼란스럽지 않을 듯 하다.

나도 최근에는 블로그에 글을 쓸때 의미에 맞는 태그들을 쓰려고 노력하는 편인데 <p>, <blockquote>, <dl> 등 몇가지 외에는 쓸 기회가 자주 없다. 어쩌면 자주 써보지 않아서 이곳에는 이걸 써야지 하고 느낌이 잘 오지 않는 것 같기도 하고.. 앞으로 자주 쓰게 될거라 기대하면서 스타일을 미리 만들어두기로 했다. 그래서 이 포스트는 스타일이 잘보이는지 확인하는 시험용 포스트가 되겠다;; 책과 W3C의 Structured text 부분을 참고해서 써본다.

em
문장을 강조하는데 쓰인다. <i> 태그와 같은 역할을 하지만 <i> 태그는 '문자를 기울인다'는 의미고 <em> 태그는 '문자를 강조한다' 라는 의미다. 다만 강조하는 방법이 문자를 기울여 표시하는 것 뿐이다. 아쉽게도 내 블로그에서 주로 쓰고있는 굴림 폰트는 기울어지면 보기가 싫다-_-
strong
강한 강조를 할때 쓰인다. <b> 태그와의 관계는 <i> 태그와 <em> 태그의 관계처럼 디자인에 관련된 태그냐 의미에 관련된 태그냐 하는 차이가 있다. 다행히 굵은글자는 보기가 좋아서 강조할때는 <em> 태그 보다는 <strong> 태그를 주로 쓴다. 사나이라면 strong!
cite
인용문이나 참조한 문서 출처를 표기한다. 참조한 책 이름이라던가 인용한 문장을 말한 사람 또는 블로그 이름 같은걸 쓰는 것 같다. 예를들면 '실용예제로 배우는 웹표준 83페이지에 틀린 문장이 있는 것 같습니다' 처럼.
dfn
용어 묶음에 대한 정의라고 하는데 뭔지 잘 모르겠다;; 구글신께 물어보니
DFN is used to mark up terms which are used for the first time. These are often rendered in italics so the user can see this is where the term is used for the first time.
라고 하는데.. dfn은 dfn이다. 뭐 이렇게 쓰는건가?;
code
요건 좀 많이 쓴다. 문장 사이에 HTML 코드(<html>)나 프로그램 코드(<?echo "Hello world";?>)같은걸 넣을때 종종 이용함.
samp
프로그램이나 스크립트 등 무언가의 결과를 표시할때 쓴다고 한다. 예를들면 구글토크에 햄버거라고 넣었더니 '햄버거 이상으로 성숙하면 몸체의 크기는 약 1메가정도이다' 라는 결과가 출력됐다라는 식으로.
kbd
사용자가 입력한 텍스트를 표시한다고 한다. 역시 잘 모르겠지만 책의 내용을 참조하면 'Windows XP에서 악성코드 제거도구를 실행하려면 Win+R키를 누르고 mrt라고 입력하면 됩니다' 같은걸까?
abbr
생략된 약어라고 한다. <acronym>은 각 단어의 머릿글자를 딴 것을 말하고 <abbr><acronym>의 상위 개념이며 단어의 일부만 잘라서 쓰기도 한다. 예를들면 abbr, fri, ad 이런 식. (앞 문장에 <abbr> 태그로 원래 단어를 넣어줬지만 익스플로러에선 스타일 지정도 무시되고 마우스를 올려놔도 아무 것도 나오지 않는다)
acronym
Cascading Style Sheet를 줄여서 CSS 라고 표시하는 것처럼 단어의 첫글자를 조합해 만든 것. <acronym>은 익스플로러에서 마우스를 올려도 풍선도움말이 잘 뜬다. 다음 단어들에 마우스를 올려보자. CSS, XHTML, AJAX
q
문장 도중에 줄을 바꾸지 않고 짧은 글을 인용할때 쓴다고 한다. 웹브라우저는 <q> 태그로 묶인 부분 앞뒤로 따옴표를 삽입해주고 <q> 태그 안의 <q> 태그에는 작은 따옴표를 넣어주며 따옴표는 각각의 언어에 적합한걸로 알아서 넣어주도록 W3C는 권고하고 있지만 아직 파이어폭스에서는 큰따옴표만 삽입되고 익스플로러는 아무것도 삽입되지 않는다. 이 문장이 따옴표로 감싸져 있으면 제대로된 웹브라우저임.
blockquote
좀 길다싶은 문장을 인용할때 사용하는 태그. 아마 가장 즐겨쓰이는 태그가 아닐까 싶다. 스타일을 이쁘게 주고 문서 곳곳에 삽입하면 상당히 폼이 난다 -_-)=b 위에 dfn 설명할때 인용된 부분이 <blockquote> 태그로 묶인 부분이다.
lang 속성
다른 태그들도 마찬가지지만 특히 <q>, <blockquote>로 인용된 부분은 lang 속성으로 원래의 언어를 정확히 표시하도록 하고있다. 예를들면 祖(조상 조)같은 경우에 한국어코드(ko)로 보는 글자()와 일본어코드(ja)로 보는 글자()가 모양이 다르다. 지금은 태터툴즈가 euc-kr 코드로 작성돼있어 앞의 빨간글씨로 된 두 한자가 똑같은 모양으로 보이지만 utf-8 버전으로 업그레이드 되면 두 한자의 모양이 달라질 것이다. 아무튼 요점은 다른 언어로 인용된 문장에는 <q lang="ja">日本語</q> 같은 식으로 lang 속성에 언어 코드를 지정해줄 것. XHTML 에서는 lang 속성 대신 xml:lang 속성을 사용하는데 하위호환성 문제때문에 당분간은 <q xml:lang="ja" lang="ja">日本語</q> 이렇게 두가지 모두 표시해줘야 한다.
ins, del
문장을 무효화(?)시키기 위해 <s>, <strike> 태그를 많이 쓰는데 지금은 권장되지 않는 태그이다. (취소선이 필요하면 CSS를 이용할 것) 대신 <del>이라는 태그를 사용해서 문장을 들어내고 <ins> 태그로 정정된 내용을 쑤셔넣는게추가하는게 바람직하다.

적재적소에 용도에 맞는 태그를 쓰도록 꾸준히 관심을 기울여야겠다. 사실 당장에는 필요가 없을 수도 있겠지만 책의 본문을 빌면,

...저금통에 동전을 하나씩 저금하는 것과 비교해 생각해보세요. 지금 당장은 큰 돈이 아니겠지만 나중에 그 정보들이 쌓인 것을 보면 매우 기쁠 것입니다.

라고 하는데 맞는 말인 것 같다. 또 하나하나의 포스트에 정성을 기울인만큼 애착도 커지는 법이니까.

얼른 책의 나머지 부분도 읽어야겠다. 이 책 굉장히 재밌음!

'컴퓨터 얘기 > 프로그래밍' 카테고리의 다른 글

태터툴즈 0.96용 노가다 유틸  (5) 2005/08/13
태터툴즈용 간단한 통계 그래프  (9) 2005/08/12
실용예제로 배우는 웹표준  (7) 2005/08/11
Google Talk  (8) 2005/08/09
우라질 쫀듸기같은 GD  (3) 2005/07/21
MSN으로 태터툴즈 댓글 알림받기  (16) 2005/07/15
태그 : 웹표준

Google Talk

구글이 말을 한다. google talks
Google Talk Project
구글 가라사대

예전부터 해보려고 마음먹고 있었던건데 몇번 포기하다가 오늘 대충 완성시켰다. 위에 첫번째 링크 누르면 나오는 KLDP 게시물에서 처음 알게됐는데 perl 돌릴만한 환경이 안돼서 PHP로 만들어봤다. 내껀 코드가 열라 지저분한데 perl은 라인도 저렇게 짧고 간결하다니.. 문법은 잘 모르지만 perl에 정규식 적당히 섞어서 적은양의 코딩으로 짜놓은거 보면 뭔가 마술같아서 배워보고 싶은 욕구가 2g정도 솟아오른다.

구글만담;; 보러가기
(소스파일)

이상하게 IE외의 브라우저는 한단어만 읽어오고 멈추는데 왜그러는지 알아봐야겠다. 좀 더 그럴듯한 말이 나오게 손도 좀 봐야겠고.. 어찌 이런걸 다 생각해냈는지 보고있으면 참 재밌다. 문맥은 잘 이어져가는데 앞뒤 얘기는 안맞는 기묘한 문장들;; 아래는 몇가지 샘플.

오늘의 날씨는 꾸물꾸물 흐리다 가도 맑아지기 시작 하고 정맥과 실핏줄들이 두드러지기 시작합니다 사회적으로 명망 있고 신뢰받는 신문을 만드는데 앞장섰습니다 경찰을 피해 도망치게 하시지 않는 한 전기 요금을 과다징수했다는 주장은 전혀 꺼릴 게 아니라 불안하고 위태롭다는 것을 알아채고 방앗간으 로 갔었다 그 동네에
사실은 채시라 팬인데 채시라를 보고 싶어 랑 버지니아 에 있는
오늘 점심메뉴는 삼계탕 토속촌가서 먹어 줘야 하고 혜택도 누리고… 단 정훈관에서는 지방청 청문감사담당관 과 이번 앨범에서 제이 케이는 자신이 UFO를 믿는 그런 은혜가 될 것 단식농성대표단은
전두환 구속은 법절차에 의한 정당한 지시를 어기고 콜 call ▣
고이즈미는 김정일로부터 최대의 통큰 졸속행정입니다 무엇보다 물고 물리 면 그냥놔둠 ㅡㅡ 글쓴이 과객 tikky ★ i node 테이블 및
문근영 졸업사진을 접한 네티즌들은 사진 속에 갇혀 있게 되는데요 출혈이 되는 성향을 보일지도 모른다 물론 철없기로는 맨날 그러면서 안 주더라구요
태터 툴즈로 당첨됐습니다 박수 건강학은 손의 기능에서부터 비롯된다 손바닥에는 3백40가지 경혈이 있고 심장과 호흡기 에도 좋은것으로 김용수 사장은 사이트별로 싸게 파는 사이트좀 알려주세요 질문 이성연애결혼 여러분 답변좀 ㅁ MuDaePpo님에
하지만 피카츄가 출동하면 어떨까 이때 얼마나 초조한지 모르는 때에 그의 안타까운 바람이다
김치 속을 채우면 디저트가 탄생하게 된다 마침내 최후의 코너를 돌았고 어쨌든 생방송으로 진행하는 음악프로그램이 있었습니다 우리 할머니 도 여자다… 할머니도 오셨죠

'컴퓨터 얘기 > 프로그래밍' 카테고리의 다른 글

태터툴즈용 간단한 통계 그래프  (9) 2005/08/12
실용예제로 배우는 웹표준  (7) 2005/08/11
Google Talk  (8) 2005/08/09
우라질 쫀듸기같은 GD  (3) 2005/07/21
MSN으로 태터툴즈 댓글 알림받기  (16) 2005/07/15
인터넷 만화 RSS 몇개  (14) 2005/06/14
태그 : Google

우라질 쫀듸기같은 GD

같은 코드가 환경에따라 이렇게도 나오고 저렇게도 나온다. 근데 이게 사소한 것도 아니고 그래픽 처리에 상당히 많이 이용될 것 같은 부분에 이렇게 버그가 있다는건 좀 이해가 안간다. 지금까지 발견한건 두개. 문제가 된 두대의 컴퓨터의 세팅은 각각 Linux + PHP 4.3.1 + GD Version 2.0 or higher (Cafe24 계정이다), WindowsXP + PHP 4.3.10 + GD Version bundled (2.0.28 compatible) (이건 집 컴퓨터)

imageCopyResampled

원본 이미지의 src_x, src_y 부터 src_width, src_height 만큼을 잘라 대상 이미지의 dst_x, dst_y 좌표에서 dst_width, dst_height 만큼의 공간에 이미지를 늘이거나 줄여 복사해주는 함수다. 문제가 되는 부분은 src_x, src_y 에 특정한 값을 셋팅해도 무조건 0으로 받아들인다는 점. 그래서 src_x, src_y 가 0이 아닌 특정 부분으로부터 이미지를 읽어오는게 불가능하다.

해결방법은 임시로 캔버스를 하나 만들어 imageCopy 함수를 이용해 원본 이미지로부터 이미지를 복사해 캔버스에 붙여넣은 다음 imageCopyResampled 함수로 임시 캔버스에 복사해둔 이미지를 원하는 위치에 붙여넣으면 된다.

PHP 4.3.11 + GD bundled (2.0.28 compatible) 버전을 사용하는 몇몇 컴퓨터에서는 제대로 돌아가기도 함

테스트 코드

<?    header("Content-type: image/jpeg");    $old_image = imageCreateFromJpeg("test.jpg");    $new_image = imageCreateTrueColor(640, 480);    imageCopyResampled($new_image, $old_image, 0, 0, 144, 66, 640, 480, 360, 200);    imageJpeg($new_image, null, 100);?>
imageColorTransparent

imageCreateTrueColor 함수로 생성한 캔버스는 검정색 바탕인데 imageColorTransparent 함수를 이용하면 바탕색을 투명하게 만들수 있다. 하지만 상황에따라 제대로 동작하지 않는 경우가 있는데..

아래의 테스트 코드를 실행하면 100x100 사이즈의 투명한 PNG 파일이 만들어져야 하지만 내가 테스트 한 곳에서는 그냥 검은색의 박스만 만들어졌다. 테스트를 부탁드린분의 PHP 5.0.4 + GD Version bundled (2.0.28 compatible) 환경, 같은 버전의 GD를 쓰는 또다른 곳의 PHP 4.3.10에서는 정상적으로 투명한 이미지가 만들어진걸 확인할 수 있었다.

코드가 정상적으로 돌아가는 곳에서 만들어진 PNG라도 파이어폭스나 IE의 alphaimageloader 필터에서는 정상적으로 투명한 이미지로 보이지만 일반적인 이미지 뷰어나 포토샵등에서는 그냥 까만색 박스로 보이는 문제가 있다. 그래서 투명한 캔버스 위에 이것저것 얹어서 최종 결과물을 얻는데는 문제가 있어보인다. 내부적으로 투명한 이미지를 다루기 위해 임시로 사용하는데는 문제가 없는 것 같음.

테스트 코드

<?    header("Content-type: image/png");    $image = imageCreateTrueColor(100, 100);    $black = imageColorAllocate($image, 0, 0, 0);    imageColorTransparent($image, $black);    imagePng($image);?>

덧붙임,

위의 코드는 완벽하게 삽질이라는게 밝혀졌다. 음하하;; imageColorTransparent 함수는 색을 투명하게 하는게 아니고 8bit 컬러 팔레트에서 특정한 색을 투명색으로 '지정'만 해주는거다. 그래서 투명 GIF 만들때나 필요한 것이고 트루컬러 이미지를 다룰때는 필요가 없는 함수 되겠다..orz

올바른 코드

<?    header("Content-type: image/png");    $image = imageCreateTrueColor(100, 100);    imageAlphaBlending($image, 0);    imageFilledRectangle($image, 0, 0, 100, 100, 0x7fffffff);    imagePng($image);?>

이렇게 캔버스 위에 imageFilledRectangle 함수로 투명한 사각형을 그려주면 끝! 6번째 인수의 컬러값 맨 처음에 나오는 7f가 투명도를 지정하는 부분이다. 50% 투명도를 가진 빨간색이라면 0x40FF0000 이 된다.

이렇게 만들어진 PNG 파일은 당연히 포토샵등에서도 투명한 이미지로 인식해준다. 만세 -_-)/

혹시라도 다른데 문제가 있거나 내 실수로 잘못 안거였으면 좋겠는데.. 지금으로써는 문제가 있는 부분을 회피해서 이런저런 꼼수를 써야하고 그나마 다른 서버에서 제대로 돌아가준다는 보장이 없으니 난감하다. ImageMagick 같은 라이브러리를 쓰고싶어도 GPL의 압박으로 낭패. PHP4에 어마어마한 결함이 발견돼서 사람들이 전부다 PHP5로 업데이트 하는 사태라도 일어나길 바란다-_-

MSN으로 태터툴즈 댓글 알림받기

Trackback : MSN Alert 설명, MSN Alert 테터툴즈 플러그인

이 내용은 태터툴즈 0.961 기준임

화니님이 개발하신 MSN 봇을 이용해서 미리 등록된 아이디로 메세지를 전송할 수 있는 인터페이스를 테스트중이시라고 한다. 간단한 가입절차를 거친 후 사용할 수 있는데 태터툴즈 외에도 사용 가능한 범위가 아주 많다. 태터툴즈에서 댓글, 트랙백, 방명록 알림으로 사용하려면 아래처럼 하면 된다.

  1. 아래의 주소로 이동해 회원가입
    http://d-3-b.com/miniboard/member.php?id=free&url=http://d-3-b.com

  2. 아래의 주소로 이동해 표시되는 메일 주소를 MSN에 친구로 추가한다
    http://msn.d-3-b.com/list.html

  3. inc_function.php 파일의 맨 끝에 아래 함수를 추가한다. 첫부분의 your_id, your_password 부분에는 1번에서 가입할때 적은 아이다와 비밀번호를 넣으면 된다.

    function msn_send($msg)
    {
        $id = "your_id";
        $pw = "your_password";

        if($fp = @fsockopen("msn.d-3-b.com", 80))
        {
            fwrite($fp, "GET /msn/call.html?id=$id&pw=$pw&msg=".urlencode($msg)." HTTP/1.0\r\nHost: msn.d-3-b.com\r\n\r\n");
            fclose($fp);
        }
    }
  4. add_exe.php 파일 28번째줄 setcookie 다음줄에 아래의 구문을 삽입한다

    if($c_name != "관리자")
        msn_send("${c_name}님이 코멘트를 남기셨습니다.\r\n".stripslashes(str_trans_rev($c_body))."\r\n${s_root_path}index.php?pl=$num");

    이렇게 하면 '관리자'라는 아이디로 쓴 댓글은 알림이 오지 않는다. 저부분을 원하는 아이디로 교체해 넣으면 된다. (원하지 않으면 if 줄을 삭제해도 됨)

  5. rserver.php 파일 27번째줄 echo 윗줄에 아래의 구문을 삽입한다

    msn_send("$blog_name 블로그에서 트랙백을 남기셨습니다.\r\n".stripslashes(str_trans_rev("$title\r\n$excerpt"))."\r\n${s_root_path}index.php?pl=$no");
  6. index.php 파일 42번째줄 if 다음줄에 아래의 구문을 삽입한다

    msn_send("${guest_input_name}님이 방명록을 남기셨습니다.\r\n".stripslashes(str_trans_rev($guest_textarea_body))."\r\n${s_root_path}index.php?md=guest");

아직 안정성 테스트 중이라고 하시는데 아주 가끔씩 몇초간 알리미가 로그아웃상태가 되는걸 빼면 큰 문제는 없는 것 같다. MSN 계속 띄워두시는 태터툴즈 유저분들께 강추!!

태그 : MSN, 태터툴즈

인터넷 만화 RSS 몇개

여기저기 돌아다니면서 만화보기 귀찮아서 만들어야지 만들어야지 하고 미루다 이제서야 만들었다. 아래의 실행파일은 모두 이 포스트http.php 파일을 필요로 하니 다운받아서 같은 디렉토리에 넣어줘야 한다.

주의사항,

마린블루스와 수야스토리는 이미지 링크가 금지돼있어서 엑박이 뜨는관계로 이 포스트의 다용도 getExtImg.php 를 한번 거쳐오게 만들었으니 저걸 받아서 계정에 올려두고 http://YOURHOST.COM/getExtImg.php 부분을 찾아 자신의 환경에 맞게 고쳐야 한다.

그리고 트라우마는 스포츠서울 사이트에 로그인을 해야 볼 수 있기때문에 rss_trauma.php 파일 19번째 줄의 YOURID, YOURPASS 부분에 자신의 아이디와 패스워드를 넣어야 한다.

rss_lasvegas.php

라스베가스디스코익스프레스

rss_love.php

애욕전선 이상없다

rss_trauma.php

트라우마

rss_marineblues.php

마린블루스

rss_suya.php

수야스토리

rss_timing.php

강풀의 타이밍

rss_tig.php

디스이즈게임 카툰

rss_catsbe.php

위대한 캣츠비

사이트 구조가 바뀌어서 어느날 갑자기 안돌아간다던가 버그를 발견하시게 되면 알려주세요. 즉시 수정하겠습니다. 혹시 RSS 리더로 보고싶은 만화가 더 있으시다면 추가요청을 하셔도 좋지만 많이 알려져서 좋을 내용은 아니니 다른 곳에서의 언급은 지양해주셨으면 합니다;;

덧붙여 각 만화 작가님들께는 이런식으로 알맹이만 쏙 뽑아다 보게 돼서 죄송하다는 말씀을 드리고 싶네요 이놈의 귀차니즘 ㅜ.ㅜ

태그 : RSS

태터툴즈 고쳐쓰기 #12 - 답글에 국가 아이콘 표시하기

lunamoth님의 제보에 따라..;

답글의 IP를 조회해서 어느 국가의 IP인지 국기 아이콘으로 표시해주는 워드프레스 플러그인베껴참고해서 태터툴즈에서 돌아가는 코드 몇줄을 만들었다. (pionelle님의 워드프레스 플러그인 소개 포스트에 있는 내용중 상당 부분을 중복해 적습니다)

1. DB 테이블 만들기

ip2nation 사이트에 접속해 왼쪽 메뉴중 Download를 눌러 sql 파일을 다운로드 받은 뒤 mysql에서 실행시켜 테이블을 생성시킨다. ip2nation, ip2nationCountries 두 테이블이 생성되면 성공. SQL 파일로 테이블 생성하는 법을 모른다면 MySQL DB 백업/복원에 대해 검색을 해보자; (ip2nation DB는 매월 업데이트 된다고 한다)

2. 국기 이미지 구하기

frenchfragfactory 사이트에 접속해 /download/utils/flags.zip 를 클릭하면 다운받을 수 있다. 다운받은 이미지는 사용중인 스킨 디렉토리 아래 images/flags 디렉토리에 넣었다고 가정하고 아래 내용을 계속한다.

3. inc_function.php 파일 수정

inc_function.php 파일 404번째줄부터 시작하는 get_rp_content($skin, $num) 함수의 447번째줄 if ($rno == "0") $bf2_rep = $skin->s_rp_rep; else $bf2_rep = $skin->s_rp2_rep; 문장 바로 다음줄에 아래 세줄을 삽입한다.
$ip2nation = mysql_fetch_array(mysql_query("SELECT c.country, c.code FROM ip2nationCountries c, ip2nation i WHERE i.ip<INET_ATON('$ip') AND c.code=i.country ORDER BY i.ip DESC LIMIT 1"));
$bf2_rep = str_replace("[##_rp_rep_country_name_##]", $ip2nation[0], $bf2_rep);
$bf2_rep = str_replace("[##_rp_rep_country_code_##]", $ip2nation[1], $bf2_rep);

4. 스킨 파일 수정

skin.html 파일의 리플을 출력하는 곳인 <s_rp_rep></s_rp_rep> 안쪽의 적당한 위치에 아래처럼 아이콘 이미지 태그를 삽입한다.
<img src="./images/flags/flag_[##_rp_rep_country_code_##].gif" width="18" height="12" alt="[##_rp_rep_country_name_##]">

5. 여기까지 하면 답글 부분은 끝. 방명록에도 추가하고 싶다면,

이번엔 inc_presswork.php 파일을 열어서 318번째줄부터 시작하는 get_guest() 함수의 428번째줄 $p2_rep = $GLOBALS["skin"]->s_guest_rep; 문장 다음줄에 아래 세줄을 삽입
$ip2nation = mysql_fetch_array(mysql_query("SELECT c.country, c.code FROM ip2nationCountries c, ip2nation i WHERE i.ip<INET_ATON('$ip') AND c.code=i.country ORDER BY i.ip DESC LIMIT 1"));
$p2_rep = str_replace("[##_guest_rep_country_name_##]", $ip2nation[0], $p2_rep);
$p2_rep = str_replace("[##_guest_rep_country_code_##]", $ip2nation[1], $p2_rep);

462번째줄 $p3_rep = $GLOBALS["skin"]->s_guest_reply_rep; 다음줄에도 아래의 세줄을 삽입
$ip2nation = mysql_fetch_array(mysql_query("SELECT c.country, c.code FROM ip2nationCountries c, ip2nation i WHERE i.ip<INET_ATON('$ip') AND c.code=i.country ORDER BY i.ip DESC LIMIT 1"));
$p3_rep = str_replace("[##_guest_rep_country_name_##]", $ip2nation[0], $p3_rep);
$p3_rep = str_replace("[##_guest_rep_country_code_##]", $ip2nation[1], $p3_rep);

6. 다시 스킨 파일을 열어서..

<s_guest_rep></s_guest_rep> 태그로 둘러싸인 방명록 본문의 적당한 곳과 <s_guest_reply_rep></s_guest_reply_rep> 태그로 둘러싸인 방명록 답글의 적당한 곳에 각각
<img src="./images/flags/flag_[##_guest_rep_country_code_##].gif" width="18" height="12" alt="[##_guest_rep_country_name_##]">
이렇게 이미지 태그를 똑같이 추가해주면 모두 끝난다.

방명록 답글에는 굳이 넣지 않아도 될 듯 하지만 손님이 답글을 다는 경우도 있어 그냥 넣기로 했다. 그리고 국기 이미지인 flags.zip 파일에 모든 국가의 국기가 들어있지 않음에 주의.. 달아놓고 방명록을 쭉 살펴보니까 우즈베키스탄(!) 아이피를 쓰시는분이 계셨는데 아이콘이 없다. img 태그 안에 onerror="this.src='./images/flags/flag_defalut.gif'" 하는 식으로 아이콘 없을때 기본 아이콘을 보여주도록 추가하면 좋을 것 같다.

근데 국기 아이콘에 그라데이션(?)이 들어가서 썩 예쁘지는 않네..;; (특히 태극기) 시간날때 살짝 고쳐봐야겠다.
태그 : 태터툴즈

태터툴즈용 Google Sitemap

Trackback to :: 구글 검색엔진 등록 - Google Sitemap

Google Sitemaps (BETA)

항상 최신의 내용을 긁어올테니 정보를 쏴주시오!! 라는데 사용자 입장에서도 당연히 환영할만한 일이다. 네이버에 검색되기 위해 한달에 몇십만원식 내야되는 것에 비하면야 구글은 컨텐츠만 좋으면 (링크만 많이 당하면) 상위에 랭크되니.. 아무튼 이게 뭔지 느껴보기 보다는 일단 해보고 싶다는 생각에 이 포스트를 참고해서 급조했는데 첫번째로 만들었던 XML을 submit 하고 한참을 기다리니 Status가 Invalid Date로 나와버린다;; <lastmod> element는 ISO 8601대로 하면 된다고 하는데 1997-07-16T19:20:30+01:00 처럼 표시했더니 에러가 발생한다. 이유는 미스테리..;; 그래서 포스트 시간을 GMT로 바꿔 1997-07-16T19:20:30Z 처럼 표시해주니 잘 된다.

아래 소스를 태터툴즈가 설치된 디렉토리에 적당한 이름으로 저장해두고 Google Sitemaps에 등록하면 된다. 별달리 설정할건 없고 기본적으로 모든 포스트를 가지고 XML을 만드는데 속도가 문제되거나 포스트 개수가 5만개가 넘을경우에는 (설마..) 25번째줄을 지우고 24번째줄의 주석을 풀어서(//를 삭제) 태터 환경설정에서 정해준 XML 아이템 개수만큼만 출력하도록 한다. (또는 적당한 개수를 LIMIT x, y 하는 식으로 지정..) 그리고 블로그 메인의 최근 수정시간은 포스트, 리플, 트랙백중 가장 최근의 시간을 넣게 돼있는데 항상 현재시간으로 설정하고 싶으면 19번째줄을 지우고 18번째줄의 주석을 풀어준다. (역시 //를 삭제) 수정시에는 파일을 꼭 UTF-8로 저장하도록 주의해야 한다.
<?
    require "inc_global.php";
    require "inc_function.php";

    header("Content-type: text/xml");

    echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n";
    echo "<urlset xmlns=\"http://www.google.com/schemas/sitemap/0.84\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.google.com/schemas/sitemap/0.84 http://www.google.com/schemas/sitemap/0.84/sitemap.xsd\">\r\n";

    list($time_post) = mysql_fetch_array(mysql_query("SELECT MAX(regdate) FROM t3_${dbid} WHERE is_public='1'"));
    list($time_reply) = mysql_fetch_array(mysql_query("SELECT MAX(regdate) FROM t3_${dbid}_reply WHERE is_secret=0"));
    list($time_trackback) = mysql_fetch_array(mysql_query("SELECT MAX(regdate) FROM t3_${dbid}_trackback"));

    echo "<url>\r\n";
    echo "<loc>$s_root_path</loc>\r\n";
//  echo "<lastmod>".gmdate("Y-m-d\TH:i:s\Z")."</lastmod>\r\n";
    echo "<lastmod>".gmdate("Y-m-d\TH:i:s\Z", max($time_post, $time_reply, $time_trackback))."</lastmod>\r\n";
    echo "<changefreq>always</changefreq>\r\n";
    echo "<priority>1.0</priority>\r\n";
    echo "</url>\r\n";

//  $result = mysql_query("SELECT no, regdate FROM t3_$dbid WHERE is_public='1' ORDER BY regdate DESC LIMIT 0, $p_xml_cnt");
    $result = mysql_query("SELECT no, regdate FROM t3_$dbid WHERE is_public='1' ORDER BY regdate DESC");

    while(list($no, $regdate) = mysql_fetch_array($result))
    {
        echo "<url>\r\n";
        echo "<loc>${s_root_path}index.php?pl=$no</loc>\r\n";
        echo "<lastmod>".gmdate("Y-m-d\TH:i:s\Z", $regdate)."</lastmod>\r\n";
        echo "<changefreq>daily</changefreq>\r\n";
        echo "<priority>0.8</priority>\r\n";
        echo "</url>\r\n";
    }

    echo "</urlset>\r\n";
?>

날씨를 보여주는 자바스크립트

기상청에서 제공하는 날씨정보 XML은 미리 허락된 날씨 정보업체에서만 사용이 가능하다고 하지만 나를 포함해 여기저기서 쓰고 있는 사람이 꽤 많은데도 굳이 막지 않는걸 보면 암묵적으로 사용에 동의하고 있는지도 모르겠다. 그리고 사실 이런건 공공재라고 볼 수도 있는데 막으면 좀 섭섭하지.. 우리나라 기상청 서버 놔두고 외국 날씨 서비스에 가서 기온 가져오는 것도 웃기고..

위에는 쓸데없는 소리였고;; 이 홈페이지 오른쪽 밑에 나오는 날씨 아이콘은 메인페이지를 호출할때마다 기상청에 접속해서 날씨를 읽어온 후 아이콘을 불러오게 된다. 그 과정에서 조금이지만 로딩 시간이 길어지고 내 홈페이지의 트래픽도 증가하는 문제가 있는데 이걸 스크립트로 만들어 사용자에게 떠넘겨버리면 어떨까 싶어 한참전부터 시도해봤지만 결국 오늘로서 포기하고 중간 결과물만 올려둔다.

이 스크립트의 치명적인 문제점은 파이어폭스(아마 넷스케이프도 해당될 듯)에서 기본적으로 XMLHttpRequest() 오브젝트를 이용해서 다른 도메인의 데이터 소스를 가져올 수 없다는데 있다. 다른 도메인에 접근할 수 있도록 대화창을 띄워 Allow 하게 하면 되지만 접속하는 사용자마다 보안경고를 보게될 생각을 하면 끔찍하다;;

여기서는 날씨정보를 담은 XML 문서를 responseText로 받아와 문자열 노가다를 하고 있는데 responseXML을 이용해서 간단하게 코딩을 하고 싶었지만 기상청 서버의 Content-type이 text/xml이 아닌 text/plain으로 잘못 설정돼있어 브라우저에서 XML로 인식하지 못하는 것 같다.

혹시 사용해보거나 테스트하고 싶은 분들을 위해 간단히 설명하자면 함수는 function getWeather(str, code) { ... } 하나뿐이니 적당한 곳에 넣어두고

<div id="weatherDiv">날씨 가져오는 중..</div>
<script>getWeather("weatherDiv", 108)</script>
이런식으로 날씨정보가 들어갈 태그에 id를 지정하고, 그 다음에 getWeather()를 호출해주면 된다. 첫번째 인수는 날씨 표시할 곳의 ID, 두번째는 지역 코드(소스 참조). 플래쉬 아이콘은 기상청 사이트에서 직접링크하게 돼있는데 본격적으로 이용해야 한다면 아이콘 정도는 자기 계정에 올려두고 사용하도록 하자.

날씨보기 링크 (소스는 소스보기로..;;)

덧.

집에와서 테스트 해보니 안된다-_-

익스플로러는 보안 설정의 '도메인 간의 데이터 소스 액세스' 옵션을 사용으로 설정하지 않으면 안되고 집의 파이어폭스는 보안 설정을 묻는 대화창이 뜨지도 않는다. 원격지의 소스를 불러오는건 애초에 불가능한건가..
이제 그냥 미련없이 포기-_- (옌장 ㅜㅛㅜ)

덧2.

영 미련이 남아서 도저히;; 그냥 내 호스트를 한번 거치게 해서 원격지가 아닌 로컬 데이터 소스로 접근하도록 변경했다. getWeather() 함수를 기상청 XML 대신 아래의 페이지를 불러오도록 수정해서 lib.js에 넣었다.

<?
    header("Content-Type: text/xml");

    $fp = @fsockopen("www.kma.go.kr", 80);

    fwrite($fp, "GET /weather/xml/current.xml HTTP/1.0\r\n\r\n");

    for($i=0; $i<8; $i++)
        fgets($fp, 1024);

    while( $buff = fgets($fp, 1024) )
        echo $buff;

    fclose($fp);
?>
이제 잘 돌아간다. 더이상 손대지 말아야지 -_- (아래는 잘 돌아가는 getWeather() 함수)

function getWeather(str, code)
{
    /*    춘천    101
     *    백령도  102
     *    강릉    105
     *    서울    108
     *    인천    112
     *    울릉도  115
     *    수원    119
     *    청주    131
     *    대전    133
     *    대구    143
     *    전주    146
     *    울산    152
     *    마산    155
     *    광주    156
     *    부산    159
     *    제주    184 */


    var obj = document.getElementById(str);
    var xml;

    try { xml = new ActiveXObject("Msxml2.XMLHTTP"); }
    catch(e) {
        try { xml = new ActiveXObject("Microsoft.XMLHTTP"); }
        catch(e) {
            try { xml = new XMLHttpRequest(); }
            catch(e) { xml = null; }
        }
    }

    if( obj && xml )
    {
        try {
            // 날씨정보가 들어있는 페이지의 경로
            xml.open("GET", "/some/where/weather.php?dummy=" + new Date().getTime(), true);
        }
        catch(e)
        { obj.innerHTML = "Failed"; return; }

        xml.onreadystatechange = function()
        {
            if( xml.readyState == 4 )
            {
                var body = xml.responseText;
                body = body.substring(body.indexOf("<l"), body.lastIndexOf("l>")+2);

                local = body.split("<l");

                var ta = 0;
                var icon = 0;

                for(var i=1; i<local.length; i++)
                {
                    var block = local[i];

                    if( block.indexOf(code) != -1 )
                    {
                        var pos1 = block.indexOf("icon");
                        var pos2 = block.indexOf("\" ", pos1);

                        icon = block.substring(pos1+6, pos2);

                        pos1 = block.indexOf("ta");
                        pos2 = block.indexOf("\">", pos1);

                        ta = block.substring(pos1+4, pos2);
                    }
                }

                if( icon )
                {
                    // 아이콘 파일의 주소
                    icon = "/some/where/sub" + icon + ".swf";

                    obj.innerHTML = "<object classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\" codebase=\"http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,29,0\" width=\"25\" height=\"25\"><param name=\"movie\" value=\"" + icon + "\"><param name=\"quality\" value=\"high\"><param name=\"wmode\" value=\"transparent\"><embed src=\"" + icon + "\" quality=\"high\" pluginspage=\"http://www.macromedia.com/go/getflashplayer\" type=\"application/x-shockwave-flash\" width=\"25\" height=\"25\"></embed></object><br>" + ta + "℃";
                }
                else
                    obj.innerHTML = "Error";
            }
        }

        xml.send(null);

        delete xml;
    }
}

200년 달력

심심해서 또 뻘짓;

예전에 배경화면으로 쓸 15년 달력을 포토샵 노가다로 만들었던 적이 있는데 이번엔 PHP로 좀 우아하게..

200년치를 출력했더니 HTML 파일 용량이 3.8메가나 한다;

읽어오는동안 익스플로러가 너무 힘들어해서 이미지로 캡쳐.

달력보기


소스파일은 아래에.. index.php 파일 맨 앞부분의 $start_year, $end_year를 수정하면 원하는 분량의 달력이 출력되는데 $start_year는 PHP가 처리할 수 있는 범위인 1902년~2038년 이내로 설정해야 된다. ($end_year는 상관없음)


만들다 문득 궁금해진건데 2038년의 한계를 지난 시점, 그러니까 유닉스 머신의 시계가 한계에 도달해 다시 원점으로 돌아갈정도가 되면 어떤식으로 문제를 해결할려나.. 인터넷을 뒤져보니 그쯤되면 지금과는 환경이 많이 바뀌게 되므로 어떻게든 해결 될테니 걱정 말라고 한다-_- 아마 대부분 타임스탬프를 64비트 변수(이정도면 향후 2천9백억년정도는 문제 없음)에 담아서 간단히 해결할테고.. 지금처럼 integer 변수에 시간을 담아쓰는 프로그램은 아마 멸종.. 34년 전과 지금을 비교해 생각해보면 전혀 예측이 불가능 할지도 모르겠다. 발전속도도 점점 더 빨라질테니.. 농담처럼 얘기했던 무한용량의 메모리 같은게 정말 개발돼버리는게 아닐까;; (이쯤 되면 프로세스가 메모리를 할당받아 쓰고 반환할 필요도 없이 그냥 버려버리는 사치를 누릴 수 있겠군!)
태그 : 삽질

태터툴즈 고쳐쓰기 #11 - UTF-8 RSS 읽기, 트랙백 보내기

태터툴즈 1.0부터는 UTF-8 기반이므로 이 내용은 1.0 미만에만 해당되는 내용임.

UTF-8 문자로 작성된 블로그에 트랙백을 보낼때면 상대방의 사이트에는 깨진 문자로 기록된다. 곧 태터툴즈 새버전에서 이 문제가 해결될 것 같지만 그때까지는 임시방편으로 태터툴즈를 약간 고쳐서 써야한다. 또, 역시 UTF-8로 작성된 RSS도 태터툴즈 리더에서는 읽을 수 없는데 이것도 간단한 변환 프로그램을 통해서 (임시로) 해결할 수 있다. 모두 iconv() 함수를 이용하는 방법이라 iconv를 지원하지 않는 서버에서는 사용할 수 없다. (예를 들면 80PORT 등)

먼저 UTF-8로 제공되는 RSS를 태터 리더에서 읽으려면,

1. 우선 HTTP 접속하는 PHP 클래스 여기 있는 http.php 파일을 받아서 계정에 올려놓고

2. 같은 경로에 아래의 코드를 utf8rss.php 등의 이름으로 저장한다
<?
    include "http.php";

    header("Content-type: text/xml");

    preg_match("/^(http:\\/\\/)?([A-Za-z0-9.]+)(\\/.*)/", $_GET["uri"], $matches);

    $h = new http($matches[2], 80);
    $h->setTarget($matches[3]);
    $h->sendData();

    echo iconv("UTF-8", "CP949//IGNORE", preg_replace("/encoding=\"UTF-8\"/i", "encoding=\"EUC-KR\"", $h->getBody()));

    $h->close();
?>

3. 원래의 RSS 주소가 http://foo.com/index.xml 이고 위에서 작성한 utf8rss.php 파일의 경로가 http://mydomain.com/utf8rss.php 라면 태터툴즈 리더 주소록에 이렇게 등록하면 끝이다.
http://mydomain.com/utf8rss.php?uri=http://foo.com/index.xml

어디까지나 임시방편이므로 에러처리 부분은 넣지 않았다. hof님 블로그가 UTF-8로 바뀐 뒤로 계속 써오는 동안 별다른 에러는 없었으니 크게 걱정할 부분은 안되겠지만.. 다시한번 강조하지만 이건 임시방편..;

그리고 태터툴즈에서 UTF-8 블로그로 트랙백을 보내는 방법

1. 태터툴즈 admin/article_trackback_pop.php 파일 100번째줄에 아래의 내용을 끼워넣는다.
<table cellpadding="0" cellspacing="0" style="margin-bottom:5"><tr>
<td width="80" align="right" style="padding-top:3">인코딩 ::&nbsp;</td>
<td style="padding-top:3">
    <input type="radio" name="encoding" id="encoding1" value="euc-kr" checked>
    <label for="encoding1">기본값</label>
    <input type="radio" name="encoding" id="encoding2" value="utf-8">
    <label for="encoding2">UTF-8</label>
</td>
</tr></table>

2. 이번엔 39번째줄에서 아래 문장을 찾아,
$data ="url=".rawurlencode($plink)."&title=".rawurlencode($title)."&blog_name=".rawurlencode($p_title)."&excerpt=".rawurlencode($body);

위 문장 바로 에 아래의 내용을 추가하면 작업 끝.

if( $encoding == "utf-8" )
{
    $plink = iconv("EUC-KR", "UTF-8//IGNORE", $plink);
    $title = iconv("EUC-KR", "UTF-8//IGNORE", $title);
    $p_title = iconv("EUC-KR", "UTF-8//IGNORE", $p_title);
    $body = iconv("EUC-KR", "UTF-8//IGNORE", $body);
}

이제 UTF-8 블로그에 트랙백을 보낼때 인코딩 항목에서 UTF-8을 체크한 후 SEND 하면 된다. (트랙백 테스트할 곳이 없으신 분은 http://crizin.net/soojung/entry.php?blogid=1 이쪽으로 가셔서 트랙백을 보내보세요)
태그 : 태터툴즈