PPTP, L2TP는 공유기 설정에 따라 사용이 불가능하거나 일부러 막아놓은 경우도 있다.


이런 저런 불편함이 있어서 OpenVPN 이란게 있는데,

자세한 내막은 모르겠지만 이 녀석을 기본 내장하는 기기는 하나도 없음.

클라이언트 설정 파일 자체가 워낙 복잡해서 그런것 같기도 하다.


여튼,

안드로이드, iOS 도 원래 OpenVPN 이 사용이 불가했다.

루팅 혹은 탈옥을 하고난 후면 사용이 됬지만.


그러다 안드로이드는 4.0 부터인가? OpenVPN 일부를 서드파티 앱의 형태로 사용가능하게 되었고

iOS 도 언제부터인지 모르겠지만 서드파티 vpn plugin 을 제공하기 시작한 것 같다.


여튼 지금 글 쓰려는건 iOS 용 OpenVPN.

(뭐 그래봤자 딱히 쓸 내용도 없고 간략한 소개 정도..)





올해(2013년) 1월달에 나왔으며 iOS 5.0 이상을 지원한다.




(443 포트로 OpenVPN 을 열면 왠만한 차단은 다 뚫을 수 있단걸 내게 가르쳐준) Private Tunnel 사의 서비스는 기본으로 지원하고,

그 외엔 클라이언트 파일을 서버로 부터 받거나,

iTunes 로 넣거나, 메일로 받으면 된다고 설명하고 있다.


web, 메일 등에서의 외부 파일 연결은 zip 등 압축은 지원하지 않고 .ovpn 만 지원한다.

iTunes 로 넣을 경우 키 파일등을 따로 넣어도 ovpn 파일 내용을 토대로 알아서 가져오는데,

web에서 가져오거나 메일로 받을때는 어떻게 되는지 모르겠다.


나 같으면 key 들을 모두 .ovpn 에 쑤셔넣었다.



Web 으로 .ovpn 설정 파일을 받을때 OpenVPN 으로 연결이 안나오고

그냥 내용물이 출력된다면 더보기 클릭!



아이튠즈로 넣든, 메일로 받든, OpenVPN 앱에서 설정 파일을 추가할건지 묻고 추가하면 이제 사용가능!





연결 잘~된다 ㅎㅎ

443 포트와 같이 원래 서드파티 앱에서 사용불가능한 포트들도 사용가능!!






앱에서 사용한 설정이 설정 앱의 VPN 메뉴에서도 볼 수 있는데,

안타깝게도 다른 설정이나 연결은 안되고 각종 설정은 앱에서 하라는 메세지가 나온다.(심지어 여기서 삭제도 안됨)

연결 중일때 해제는 가능하다.


아이튠즈에서 설정파일을 넣고, 추가하고 나면 앱의 샌드박스 내 어디에도 설정 파일을 찾아볼 수 없는 것으로 보아

VPN 설정 추가시 설정, 키들을 iOS 키체인으로 집어 넣는 듯 하다.





참고로 OpenVPN 앱 내 말고, 설정 앱 안에 OpenVPN 설정 메뉴가 생기면서 다른 설정들도 가능하다.




탈옥을 하지 않고 순정에서도 할 수 있는 작업이 점점 늘어나는건 확실히 기분좋은 일인 것 같다~

개발자용 기기는 탈옥에 맞먹는 자율성을 부여해주면 좋을텐데...ㅠㅠ

Activator 를 꺼려하는 사람이 은근히 많아서,

Activator 가 필수적이지 않은 BeeKeyboard 에서는 의존성을 없애야 겠다,, 는 생각만 하고 놔두다가

어제 weak link 로 바꿨다..ㅎ


잠깐 확인해 봤는데 잘됨!


1. Makefiles 의 LDFLAGS 를 아래처럼 사용한다

@@@@_LDFLAGS = -weak_library /opt/theos/lib/libactivator.dylib


내가 못하는건지, 원래 안되는 건지 -weak_library 로 할때는 경로 전체를 적어줘야 하더라..


2. 앱 내에선 클래스의 존재 유무로 라이브러리가 로드 됐는지 확인한다.

다른 방법도 있는 것 같지만, 난 간단하게 저렇게 했음.

확인 안하고 냅두면 크래쉬 남 ㅇㅇㅋ


Class LAE = NSClassFromString(@"LAEvent");

if (LAE != nil) {


}


요런식으로...



설정 부분 같으면 불러오는 부분은 PSListController 를 사용하고,

Activator 를 사용하는 컨트롤러에서는 내부 변수로 Activator 의 클래스를 사용하고 있어서,

PSListController 에서 tableView:didSelectRowAtIndexPath: 를 오버라이드 해서 체크하고 있다.

다른 부분에서 비슷한걸 구현해 사용하고 있기 때문에 쉽게 끝냈음 ㅋ


- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

{

    int group = [self indexOfGroup:indexPath.section];

    int pIndex = group + indexPath.row + 1;

    

    PSSpecifier* spec = [self specifierAtIndex:pIndex];

    if ([[spec propertyForKey:@"detail"] isEqualToString:@"GActivatorSettings"]) {

        Class LAE = NSClassFromString(@"LAEvent");

        if (LAE != nil) {

            [super tableView:tableView didSelectRowAtIndexPath:indexPath];

        }else{

            [tableView deselectRowAtIndexPath:indexPath animated:YES];

            NSString* message = LS(@"NEED_ACTIVATOR");

            UIAlertView* alert = [[UIAlertView alloc] initWithTitle:LS(@"BeeKeyboard") message:message delegate:self cancelButtonTitle:LS(@"OK") otherButtonTitles:nil];

            [alert show];

            [alert release];

            return;

        }

    }

    

    [super tableView:tableView didSelectRowAtIndexPath:indexPath];

}


단, 이 경우 PSListController 의 헤더에 tableView:didSelectRowAtIndexPath: 가 선언되어 있지 않기 때문에

선언해주고 써야 한다.


@interface PSListController (p)

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;

@end



+ 확실하진 않은데, PSListController 에서 불러오는 plist 에서 index 0 의 항목이 PSGroupCell 이 아닐 경우 index 번호가 한개씩 밀릴 수도 있음... ㅎㅎ;;




여튼 이렇게 하면, Activator 와의 연계 부분을 사용하고 싶은 사람만 Activator 를 설치, 사용할 수 있게 된다!


다른 Dynamic Library 나 OS버젼 따라 다른 프레임워크 등도 이런식으로 사용하면 된다.

프레임워크의 경우엔 -weak_framework 임.



고1때, 반에서 틈틈히 사진을 찍어 한달에 한번 꼴로 사진을 인화, 저런식으로 반에 붙여뒀었다

중2때 담임쌤이 사진을 반에 걸어두셨었는데 그게 생각나서 했던것 같은데...


여튼 반응은 대체로 괜찮았음ㅎㅎ 쌤들도 재밌게 보고 가시고, 애들도 대부분 좋아하고...

덕분에 1년동안 학교에서 찍은 사진들이 2천여장을 넘어섰다....ㅋㅋ


고2때는 담임쌤이 저런걸 싫어하시진 않을까 눈치만 보다가 말았는데, 그러다보니 사진도 덜찍게 되더라.

그게 좀 아쉬워서, 고3 올라와서는 반에 텅텅 빈 게시판이 있길래 쌤 허락맡고 사진 붙이기로 했음!!




1학년때에 한거에 비하면 좀 초라한가..?ㅎㅎ

교실 뒷편 벽이 다 저런 초록색 게시판인데 우측부분을 다 사진으로 채우는게 목표!

지금은 저기보다 사진이 많은데, 금방 채울 수 있을 것 같다...ㅋㅋ


원래 사진 인화는 집 앞에 사진관에, 어머니에게 부탁해서 인화했었다.(학교땜에 내가 갈 순 없으니..)

가격도 비싸고,, 편집 같은 것도 내 맘대로 못하고...

일반적인 사이즈의 인화지의 경우 사진 비율보다 가로 비율이 조금 더 길어서 위아래로 잘리게 되는데 이 부분을 내 마음대로 할 수 없는것이 제일 마음에 안들었다.



요즘에 별게 다 인터넷으로 되는데 사진인화도 할 수 있지 않을까? 라는 생각으로 사진인화 서비스를 찾아봤었다.

조건은,

1. 맥에서도 사용가능 할 것.

2. 편집을 할 수 있을 것.

3. 사이트가 전체적으로 깔끔하고 결제가 맥에서 가능할 것.

정도..? 사실 결제까지는 큰 기대 안했지만, 놀랍게도 스냅스는 이 모든걸 충족한다.


게다가 가격도 집 앞 사진관의 절반수준!! 장당 250원이라는 가격은 매번 가슴아팠는데 스냅스는

장당 139원이다.

20장 정도 인화할 경우 택배비 2500원이 추가되면서 집 앞에서 인화하는 것과 별 차이가 없다는게 문제..ㅠㅠ

편집을 내 맘대로 할 수 있다는 것에 만족하자..ㅠㅠ




사이트가 세련되게 잘 만들어져 있길래 회원가입하고 사용해 봤는데 처음 생각한 조건이 다 충족되서 놀랐음 ㅎ

결제는 아쉬운게 되긴 되는데 내가 사용하는 카드 결제방식은 지원하지 않는다..

그래도 무통장 입금이 active x 없이 가능해서 이걸로 쓰면 되니 큰 불만은 없다.


사진인화 과정은 간단하기도 하고, 잘 만들어져 있어서 그냥 따라 만들면 되지만,

그래도 한단계 한단계 글을 써보았다 ㅎ


우선 스토어 메뉴에서 사진인화를 누른다. 다른 종류도 많으니 살펴볼 것!

일단 지금은 사진인화만 하지만, 연말에 포토북으로 사진들 모아서 담임쌤들이나 친한 친구들에게 만들어주면 좋아하겠지?



스토어 버튼을 누르면 하단에 아기 사진들이 사이즈 별로 나오는데 주문하기 버튼이 있다. 사이즈별도 다 링크로 사실 뭘 클릭하던 뜨는 창은 똑같고 사이즈는 어차피 다시 선택해야 하니 아무거나 누르면 된다.


클릭하면 아래와 같은 편집프로그램이 모니터 화면 가득차서 실행된다.

컴퓨터에서 사진을 불러오면 메인 좌측에 사진이 쌓인다. 사진을 선택하고 하단부의 우측 상단에 있는 전체 담기를 누르면 원하는 사이즈를 선택할 수 있고, 선택 후의 화면은 위 스샷과 같다.

참고로 일반적으로 사진관에서 인화하면 나오는 사진의 사이즈는 (스크린샷에서 볼 수 있듯이) 4X6 이다.


그 다음 우측 상단의 다음을 클릭~

팝업이 뜨면서 편집하고 인화할꺼냐고 묻는데 그냥 네 누르자.

아니요 눌러도 편집화면을 다시 볼 수는 있다.




실제 사진으로 인화될 부분을 저 파란색 상자로 지정할 수 있어서 사진마다 적절히 조정해주고,

간단한 효과, 스티커, 텍스트 등을 할 수 있는데 솔직히 저런건 난 안쓰고, 촬영일만 넣는다.


사진 한장에서 "실제 촬영일 입력" 선택, -> 글꼴 선택 -> 전체 사진에 적용 하고나면 모든 사진에 동일하게 촬영일이 들어가는데(물론 날짜는 exif 에 따라가도록 할 수 있는 옵션이 있다.) 그리고 나서 파란색 박스 조정해준 것처럼 사진마다 조금씩 조정해주면 된다.


참고로 글꼴 부분에는 지금 버그가 좀 있는 것 같다.

저 스크린샷만 봐도 선택한 글꼴과 미리보기의 글꼴이 일치하지 않는다..

나의 경우 이거때문에 촬영일이 엉망이 되서 재주문(물론 고객센터 문의 후 무료처리)을 했는데, 재주문 하면서 저 부분도 같이 리포트 했으니 금방 고쳐지겠지...?


편집을 다하고 좌측 상단의 닫기버튼을 누르면 이런 화면을 볼 수 있다.

이 화면에서 좌측 상단의 사진추가, 사진편집 버튼을 누르면 위에서 했던 작업들의 페이지로 이동할 수 있다.


일괄옵션으로 설정 후 사진마다 각각 옵션을 따로 줄 수 있고 인화 매수도 선택 가능.

밝기보정은 뭐가 달라지는지 딱히 모르겠더라...


다 했으면 장바구니 담기 클릭!


그러면 편집창은 닫히고 장바구니가 뜬다.

여기서 결제 등 마무리 작업을 하면 됨. 뒤에는 귀찮아서 생략 ㅋㅋ


장바구니 담기 이후에도 편집을 할 수 있는데 이때 exif 의 촬영일 데이터가 이상해지는 것 같으니 확인을 잘 해보자..

이 역시 일단 리포트 해두긴 하였다.




우연히 선택한 스냅스가 내가 원한 조건도 다 충족하고, 꽤나 만족스러워서

다른 사진인화 서비스는 찾아볼 생각도 안해봤다 ㅋㅋ



사진 인화 할일이 있는 사람이나, 추억꺼리를 만들고 싶은 사람들에게 추천!!

단지 사진 찍는걸 좋아한다기 보다는 그 순간을 남긴다는 의미에서의 사진을 좋아해서 자주 카메라를 들이대고 찍는데

나만 보고 추억에 잠기는 것보다는 이렇게 인화해서 모두 함께 보는 것도 좋은 선택인것 같다.


저렇게 사진을 인화해서 걸어두면 처음에 찍히는걸 거부하는 친구들도 막상 자기 사진이 없으니까 아쉬워 하고, 다음번엔 적당히 찍힐려고 하더라 ㅋㅋㅋ

코딩하기 싫어서...ㅋㅋ

(죽어도 공부는 안하는 미친 고3..)



카톡

우선 카톡 빠른 답장 관련 글을 썼더니.. 카톡관련 리퍼러 들이 보인다..ㅋㅋ

"남친이 카톡 답장 잘 안할때", "카톡답장이없는이유", "카톡 확인하고 답장안하는 남친" 등등....


"카톡 답장하라고" 보고는 뿜었음..ㅋㅋ


답장 없는 이유야 뭐...

1. (난 안하지만) 롤 등 게임하고 있거나

2. 보고 나서 답장 하려다 그대로 망각

3. 핸드폰이 미쳐서

4.니가 싫어서(?)


이정도 겠지 뭐..

뻔한 질문을 인터넷에 묻고 그래?!! ㅋㅋ


"카톡 빠른답장", "카톡안들어가고 메세지보내기"

요런것도 있는데.. 아이폰용을 만들고 있긴 하지만 언제 될진 모름 ㅋ

기술적으론 큰 문제가 없는데.. 어떻게 해야 좋을지의 문제라고 할까나..?

그냥 단문 sms 처럼 보내기엔 재미가 없고, 카톡 채팅방을 그대로 불러오자니 이것도 뭔가 밋밋하고.. 여튼 그럼...ㅋㅋ



"앱 설치 여부 확인 safari"

예전부터 들어오던 리퍼러였지만 잘 모르겠어서 걍 씹고 있었음..

네이티브 앱에서야 IHasApp 이라는 프레임워크가 있다고 저번에 소개했었고..


문제는 웹에서인데... 보니까 확인 자체는 안되는 듯.

단지 꼼수로 url 호출과 앱설치 요구 팝업을 동시에(정확히는 url 호출을 먼저) 하는건데,

이럴 경우 설치되어 있으면 해당 앱으로 넘어가고, 설치 안될 경우 url 은 무시되고 팝업이 보인다.

단, 앱으로 넘어갔을 경우 다시 사파리로 돌아오면 팝업이 그대로 남아있는데 뭐 크게 상관없을 뿐더러

확실하진 않지만 스크립트로 죽일수 있지 않을까...??


VPN

"빠른vpn 앱"

돈주고 쓰거나 직접 구축하면 됨 ㅋ 그럼 빠름 ㅋ


"가상사설망 교육청"

사실 이거 땜에 vpn 항목을 넣었음. 저번에 다른 글에 끼워 쓴것 같기도 하지만 여튼..ㅋ

망할 교육청 네트워크는 포트들을 다 막아버려서...ㅠㅠ

포트 화이트리스트로 거르는 듯 한데 문제는 그 화이트리스트 조차 거의 없다 ㅠ

일단 프록시의 경우는 잘 되는 것 같은데...

pptp, l2tp, 일반적인 openvpn 포트는 당연히 다 막혀있고,

나의 경우 서버가 https 를 사용하지 않기 때문에 443(ssl 포트) 포트로 openvpn 을 열어서 사용했었다.

무료 openvpn 서비스 중에 443 을 사용하는게 하나 있어서 무료로 쓰는 사람들은 그거 써도 될듯..

terminal 어쩌구였는데 정확한 서비스 이름은 기억나지 않는다..


아직까지 미스테리인, 특이한 점은, 일부 안드로이드 폰들의 경우 l2tp 가 그냥 된다.....

왜 되는지는 전혀 모르겠다...........



deb

deb 만들기, package 만드는법 등의 리퍼러 들이 보이는데..(이것도 썼었나?)

윈도 계열에선 잘 모르겠다.

unix 계열에선 dpkg 설치해서 터미널상에서

# dpkg-deb -b 폴더명

하면 만들어짐. 물론 control 파일 같은것도 다 넣어놔야 겠지만....

자세히 쓰긴 귀찮고 비슷한 글을 써둔 것 같으니 찾아봐....ㅋㅋㅋ


saurik 누구

ㅋㅋㅋㅋㅋ 누구긴 누구야 ㅋㅋㅋ 사람이지 ㅋㅋㅋ

추가 - Gist 란걸 알아서 거기에도 올려봤음~ 걍 소스만 저기 다시 올린거....

https://gist.github.com/iolate/5479930




네트워크 선택... 옆에 뱅글뱅글 돌고 있는 저 인디케이터.


초기 아이폰때 부터 있던 UI 로 구현이 쉬울줄 알았다..

혹은 주워쓰면 되는 예제라던가.


근데 전혀 그렇지가 않더라...ㅡㅡ

심지어 내가 사용한 방법은 iOS6 이후만 쓸 수 있음.



우선 iOS6 이후로 UITableViewHeaderFooterView 란게 생겼다.

마찬가지로 dataSource 에

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section

라는 메서드도 호출됨. (하지면 [super ~~ ] 로 안되는걸로 봐선 구현해야지만 작동하는 듯 하다.)


설명으로 봐서는 nib 으로 커스텀 뷰를 만들고 등록 후 사용해야 하는 것 같지만

난 그럴 필요가 없기에 기본 클래스를 다시 등록하고 거기에 인디케이터만 붙였다.


대충 아래와 같이 사용.



activityIndicator 의 상태를 조절하기 위해서 따로 선언하고 사용하는게 좋다.

아쉬운 점은 초기화 되기 전에 호출되는 것인지 label 의 길이를 얻어올 수가 없다.


후에 다시 재조정해주는 방법 등으로 사용해야 할 듯.

또한 tintColor 등의 메서드에 내가 먼저 접근해버리면 이상해져 버림.


보통은 UIViewController 안에서의 메서드나, 따로 노티를 등록해서 감지하지만,

트윅에선 여의치 않거나 저 방법을 쓰기 싫을때가 있다.


각 앱에선 뭘 후킹해야 할지 잘 모르겠고 SpringBoard 에서 후킹해서 노티를 날려주는 방법으로 사용하고 있음.


출처는 MouseSupport 의 소스...ㅋㅋㅋ


%hook SpringBoard

iOS3.2~5

-(void)frontDisplayDidChange

-(void)noteInterfaceOrientationChanged:(int)orientation


iOS6

-(void)noteInterfaceOrientationChanged:(int)orientation duration:(double)duration



iOS6 의 경우 화면회전 되기 전에 호출되는 듯.(아닐 수도 있고)

orientation 인자를 받거나 0.2 초 정도 후에 회전값을 받아오면 된다.


그리고 화면 값 자체는 UIApp([UIApplication sharedApplication]) 의 statusBarOrientation 를 받아왔었는데 원래 그랬는지

iOS6 이후 바뀌었는지 SpringBoard 의 화면회전 상태만을 기억하고 받아오지, 현재 실행중인 앱의 회전 값은 받아오지 않음.

마찬가지로 UIApp의 activeInterfaceOrientation 메서드를 사용하면 정상적으로 받아올 수 있다.

만약 SpringBoard 가 아니라 각 앱에서 노티를 받는다면 크게 상관없을 거고...


iOS6 이전에도 존재했는지는 확실치 안아서 그냥 respondsToSelector 로 넘겼음.

글 자체를 통째로 번역해보는 건 처음이네..ㅋㅋ

시디아 지역화 파일 정도 번역같은건 해봤지만.....


오역, 이상한 번역투, 이해 잘못한거, 번역 못한거, 빼먹은 거 등 수정 해주시면 감사합니다~


원문 : http://iphonedevwiki.net/index.php/MobileSubstrate_Pitfalls


#: 번역 주

확장기능(extension) 은 MobileSubstrate Extensions. 즉 트윅을 뜻하는 거임

주황색 : 번역 안됨 혹은 정확한 의미를 모르겠음


===========================================================


일반적인 MobileSubstrate 의 실수들을 막기 위해서 아래 가이드 라인을 따를 것.


1. SpringBoard 를 후킹할 경우 constructor 에서 UIDevice 를 사용하지 말 것

# constructor 는 theos 의 %ctor 나 +(void)load 와 같은걸 의미하는 듯. SpringBoard 가 완전히 로드된 후에는 사용해도 된다.


2. ivar 에 접근할 때는 적절한 property 들을 통해 사용


3. 본래 작업이 동작하지 않게 하는것이 필요하지 않다면 항상 본래 작업을 호출할 것. 또한 원래 작업은 그 메소드 내부에서만 호출해야 함.

# 쉽게 말하자면 꼭 필요한게 아니라면 %orig 를 빼먹지 말고, %orig 는 후킹한 메서드 안에서만 쓰란 얘기


4. MobileLoader 필터를 항상 포함할 것

SpringBoard 를 후킹한다면 com.apple.springboard 를, 모든 UIKit 앱들을 후킹한다면 com.apple.UIKit 필터를 사용하면 됨


5. SpringBoard 안에서 UIAlertView 사용을 피하고 SBAlertItem 을 재정의 해서 쓸 것. system이 경우에 따라 alert 을 무시해도 상관없다면 UIAlertView 를 사용해도 무방.


6. 공개된 SDK 에 기술된 API 들을 쓸 것. Private API 는 Apple이 Public 이전에 테스트 목적으로 넣어둔 경우가 많으며 이 후 버젼에 같거나 비슷한 Api 가 Public 으로 공개된다.


7. Preferences 프레임워크는 iOS 버젼 3.1 과 3.2 사이에 크게 변했다. 간단한 설정엔 PreferenceLoader 와 preferences plist 를 사용하고, 아니라면 PSViewController와 UITableView 를 함께 써라. (PSListController 또한 간단한 설정에 쓰면 좋고 OS 버젼에 따른 큰 차이가 없다. PSViewController 는 훨씬 강력하지만, 3.1->3.2 로 넘어오면서 많은 메서드들이 없어졌다.)

# 나의 경우엔 UIViewController 에 -(void)setRootController:(id)controller, -(void)setParentController:(id)controller, -(void)setSpecifier:(PSSpecifier *)spec, -(PSSpecifier *)specifier, -(void)lazyLoadBundle:(id)bundle 등을 대충 정의해준 뒤 쓴다.


8. 해상도나 기기 방향에 대해 별문제 없도록 autoresizingMask 나 layoutSubviews 를 적절히 써줄 것.


9. OS 나 Cydia 파일을 변경하지 말 것. 런타임 중에 변경되도록 할 것.

# WinterBoard 가 이미지 파일을 런타임으로 변경하는걸 생각하면 이해가 쉬움. 즉 후킹하란 소리


10. 쓸데 없는 작업들은 피할 것. 확장기능의 메서드 들은 타이트한 loop 속에서 실행 된며 디스크 파일 접근이나 property 를 호출하는 것 같은 작업은 많은 일을 하는 것을 고려할 것. 작업이 느려질 수 있음.

# 하지만 경험상 별 상관없음. ctor 나 load 등 최초 실행중에 삽질만 안하면 거의 문제 안남


11. UIImage 를 포함한 UI~~ 메서드들은 반드시 main thread 에서 실행되어야 한다. 백그라운드에서 이미지를 불러와야 한다면 CGImageSource 와 그 계열 함수들을 사용.


12. main thread 를 붙잡고 있지 말 것. 어떤 작업이든 오랜 시간이 걸리는 작업(인터넷 연결을 포함하여)을 main thread 에 두는 것은 좋지 않다.


13. NSBundle 을 통하여 리소스를 사용할 것. 이것은 WinterBoard 가 theme를 적용시킬 수 있게 해준다.

# 하지만 난 NSBundle 을 한번도 쓴 적이 없지 ㅋ


14. 적절한 의존성을 Debian control 파일 안에 포함할 것. 시디아가 자동으로 설치해 줄 것이며, OS 버젼과 같은 문제가 있을 경우 이를 사용자에게 알려준다.


15. 확장기능이 다른 확장기능이 사용할 수 있는 API 를 포함한다면, 이를 기술할 것.

찾기 쉽게 패키지 안에 헤더파일을 포함해 놔도 좋다.


16. 확장기능이 지역화될 수 있도록 할 것. 일반적인 .lproj 파일을 사용하면 된다. 텍스트를 포함한 이미지 사용은 지양.


17. package 가 .DS_Store / ._* / thumbs.db 같은 파일들을 포함하지 않도록 할 것

# 포함될 경우, 필요 없는 파일이기도 하고 저 파일들이 포함된 또 다른 패키지들이 있을 경우 설치가 안될 수가 있다. make package 가 아니라 직접 dpkg 할 경우 곧잘 포함되서 좀 짜증남;;ㅋㅋ


18. 클래스의 ivar 구조를 추정하지 말 것. 펌웨어 버젼에 따라 달라질 수 있다.

# 말그대로 구조. 구조를 토대로 메모리 주소로 값들을 사용하지 말란 거지 변수이름을 토대로 ivar 을 얻어오는 것과는 다른 얘기인 듯.


19. substrate.h, CaptainHook, Logos 와 같은 인정받은 후킹 메서드들을 사용할 것. 직접 만든것 보다 더 좋으며 당장 사용할 수 있는 자세한 정보들이 많다.


20. low-level 그래픽 하드웨어에 접근할 일이 있다면, 1세대 기기들은 통일된 메모리 모델을 가지고 있지 않음에 주의. (VRam 과 규칙적인 RAM 은 분리되어 있다.)

# 뭔소린지 모르겠지만 우린 1세대 기기와는 상관없으니 무시.


21. iOS의 Memory-Warning 시스템에 참여할 것. 확장기능이 많은 메모리를 사용한다면, 가능한 모든 것들을 해제할 것.


22. 큰 dataset 을 사용할 경우 mmap 을 사용. 커널이 필요에 따라 스왑할 것이다. (하지만 큰 작성은 피할 것, 가상메모리 보다 나은게 없어질 것이다.)

# 뭔소린지 모르겠다..


23. MobileSubstrate의 Safe Mode 를 방해하지 말 것


24. 확장기능이 홈화면의 아이콘을 다룬다면, IconSupport 를 사용함으로써 다른 확장기능의 수정이나 safe-mode layout 을 건드리지 말 것.


25. 가능한 최신의 펌웨어를 지원할 것 - "3.0.1, 3.1 이후 지원" 말고 "3.0 부터 지원" 이렇게 하란 뜻. 필요하다면 버젼을 감지해서 다르게 작동하도록 만들 것.


26. 사용자의 개인정보를 존중할 것.

IMEI, 전화번호, 연락처, 메일은 명백히 개인정보이다.

MAC 주소, Bluetooth MAC 주소, UDID 같은 것이 유저를 식별하기 위한 정보로 사용될 수 있다.


27. 숨겨야 할 것이 있다면, Strip symols 할 것. Objective-C 는 자세한 것까지 보여주니 일반적인 C 나 C++ 을 사용할 것

# 사실 그래도 다 보임. inline 으로 쓰고, ldflags 에 -Xlinker -unexported_symbol -Xlinker "*" 을 넣으면 그나마 덜 보인다고 함.


28. 많은 Private Framework 의 헤더들은 Mac 용 Public Framework 로 공개되어 있으니 그거 쓰면 됨. 혹은 다른 사람들이(kennytm 등) 추출해 놓은 header 들을 사용.


29. 사용하는 Framework 만 링크할 것. 필요없는 프레임워크의 링크는 실행 속도를 저하시킬 수 있음. (앱이 실행된 이후 런타임에서 라이브러리를 로드하기 위해서는 dlopen/dlsym 을 사용)

iOS3.1 이후에는 dyld shared object cache 덕분에 크게 상관 없음. 그래도 필요없으면 뺄 것.


30. Class 이름이나 Category 이름 앞에 Prefix 를 붙여 사용할 것. Objective-C 는 Namespacing capabilities 를 사용하지 않는다. (예를 들어 같은 이름의 클래스가 확장기능과 그 확장기능이 후킹한 앱에서 사용된다면 둘중 하나는 제대로 작동하지 않을 수 있음.)

# 이거 중요함. 이거 때문에 뜬금없이 앱이 오작동하는 일이 많다. UIKit 이나 Foundation 에 카테고리로 메서드를 추가할때도 특히 유의. 예를 들자면(실제 경험) UIView 에 viewController 라는 메서드를 새로 정의해놨는데 이게 앱에서도 똑같은 이름으로 정의해놨지만 앱쪽은 코드가 조금 달랐는지 앱이 제대로 작동 안했었음. 중복될 만한 클래스 명이나 메서드명 앞에는 A_ 같은 식으로 prefix 를 넣어주자. 수정해주기 귀찮으면 define 으로 처리해도 됨.


31. 설정 파일은 /var/mobile/Library/Preferences/ 안에 넣어둘 것. iTunes와 iCloud 가 이것을 백업한다.


32. sandbox 제한을 피해서 데이터를 저장하기 위해서는 필요에 따라 /var/mobile/Library/AddressBook/ 이나 /var/mobile/Library/Keyboard/ 를 사용.

# 샌드박스를 깨주는 라이브러리(혹은 트윅)도 있는 것으로 앎. 필요하다면 알아서 검색~


33. 잠자기에서 폰을 깨우거나 잠자기에 들어가는 것을 방해하지 말 것. 확장기능이 주기적으로 해야할 일이 있다면 Mail 앱의 동기화 부분을 후킹하여 사용. (스케쥴/알람 기능을 가지는 확장기능 들은 이 경고를 무시해도 된다.)


34. 배터리를 위해서 사용자가 예상할 수 없는 CPU, GPU, 디스크 작업은 피할 것


35. NSLog, CFLog, fprintf(stderr, ...) 등을 남용하지 말 것. 이것은 느리고 동기적(?, synchronous)이다.


36. 확장기능이 아이콘을 보여준다면, 29*29와 59*60의 사이즈를 둘다 포함할 것 (more for iPad.)


37. 다른 확장기능이 같은 메서드를 후킹할 것을 염두에 둘 것. 그들은 이 가이드라인을 읽지 않고 미친 짓을 할 수도 있다.


38. Prefer hooking methods over hooking functions--new jailbreaks don't always have kernel patches (although this is not as much of a concern, as jailbreakers understand the need for W^X) and MobileSubstrate may not support newer ARM instructions.

# 뭔소린지 잘 모르겠지만 low-level 의 함수들은 가급적 후킹하지 말란 소리 같음..


39. Public API를 후킹할 경우 return 값의 클래스를 바꾸지 말 것. 일부 AppStore 앱들은 객체의 클래스를 확인하지 않고 문제를 일으킨다.


40. XML 보다 더 빠른 binary plist 를 선호할 것. (OpenSTEP 스타일의 plist 또한 빠르지만 deprecated 된 것으로 보임.)

# binary plist 는 어떻게 만드는건지 모르겠다. 그냥 NSDIctionary 에 있는대로 써도 됨


41. Cocoa 메모리 관리 가이드 라인에 따라 모든 후킹에서 한줄한줄 정확하게 메모리 관리를 할 것.


42. MSHookMessage 대신 MSHookMessageEx 를 사용할 것.

MSHookMessage allows you to specify an optional prefix which gets added to the original method, polluting the class.

나같으면 @deVbug0 님의 도움을 아~주 많이 받았지만

도움을 못받는 사람도 있을거고 안받을려는 사람도 있을거고.....


뭐 여튼 트윅제작에 대해 대충 써본다. (사실 나도 잘 모른다)


0. Tweak?

트윅을 시디아스토어에 올라온 모든 앱을 통칭하는 정도로 쓰는 사람들이 있는데 그건 아니다.


Tweak 의 사전적 의미는 뒤틀다, 수정하다 정도가 된다.

이 의미에서 알 수 있듯이 Tweak 은 이미 있는걸 수정하는 앱이다.


대표적으론 SBSettings 와 Activator 같은 것들.

이미 있는 SpringBoard(잠금화면, 홈화면 등을 주관하는 앱이 SpringBoard 이다.)를 수정하여

SBSettings 를 보이게 하고, 특정 동작에 대해 다른 작업을 할 수 있게 하는 것이다.


이를 위해서 다른 앱을 후킹해야 하는데 이 작업을 saurik 이 MobileSubstrate 란 앱으로 잘 해결해 놨다.

이부분에서 잘은 모르겠지만 앱 실행시 트윅용으로 제작된 동적라이브러리를 MobileSubstrate 가 강제로 load 시키는 듯?

탈옥툴의 성능(?)이나 MobileSubstrate 의 한계 등으로 후킹이 안되는 것들도 있다던데 이부분은 여전히 이해가 안간다..


여튼 iOS 내에선 저런게 있고, 개발시에는 substrate.h 의 함수들이 있지만 CaptainHook 나 logos(theos 에서 사용가능한 언어)로 쉽게 후킹가능하게 만들어져 있다. theos 의 경우 후킹하기가 매우 쉬움!



1. THEOS

본래는 크로스컴파일러로 시작한 것 같은데 어차피 컴파일러 등 맥이 필요한게 사실이고

사실상 맥에서만 돌아간다.(삽질을 많이 하면 리눅스기반에서도 돌릴 수는 있는 듯)

나의 경우 처음엔 템플릿을 내려받아 xcode 에서 mobilesubstrate base (즉 트윅) 를 개발했었는데

여러가지로 불편한 점도 많고 강력한 logos 언어를 사용할 수 없어서 theos 로 돌아왔음.


또한 초기에 PreferenceBundle 을 제작하고 싶어도 어떻게 할 줄을 몰라서 생ㅈㄹ을 했었는데

그냥 theos 로 만드는 거였음...ㅠㅠ


여튼 그래서 대부분의 트윅이 theos 로 컴파일 된다고 보면 된다.

사실 이 theos 는 ios 에서도 설치, 사용할 수 있는데 ios sdk3 까지 밖에 지원하지 않는다.

다른건 상관없는데 새로 등장한 코딩기법(예를 들면 블럭코딩 등)을 사용할 수 없고 이에 따른 제약들이 있다..


맥용 설치 / 사용법은 아래 주소.. 참고로 쨋든 xcode 의 설치가 필요함.

devbug 님 이 쓰신게 한글이니 걍 저거 보고 하면 된다 ㅋ

http://devbug.me/629

http://brandontreb.com/beginning-jailbroken-ios-development-getting-the-tools/



2. Cycript

나도 뒤늦게 알았다..

그리고 매우 신기하다!!

(시디아에서 설치하거나 apt-get install cycript 로 설치할 수 있다.)


이미 실행중인 프로세스에 붙어서 메서드 들을 실행할 수 있다

테스트 같은거 할때 매우 편리!!

좀더 이해할 수 있게 말하자면.. 

터미널에서 SpringBoard 에 연결해서 아이폰에 SpringBoard 가 돌아가는 상태로 바로 AlertView 를 띄우거나, 메서드 값을 확인하거나, 후킹을 하거나(이건 좀 복잡하드라) 등등이 가능하다!!


디버거 같은거일텐데 내가 디버거를 안써봐서 잘 모름;;ㅠㅠ


자바스크립트를 obj-c 로 바꿔준다고 자바스크립트가 기본이라는데 변수 선언을 var 로 하는거 말고는 딱히 왜 자바스크립트 인지 모르겠다.

여튼 좋음. 좋다! 걍 한번 써봐라 트윅제작을 한다면 계속 끼고 살게 될것임!



3. logify.pl

써보진 않았고, @typ0s2ud10 님이 트윗에 쓰셔서 알게 된거..

$THEOS/bin/ 에 있다.

헤더 파일을 input 으로 집어 넣으면 이 헤더에 선언된 메서드들을 모조리 후킹해서 호출될때 로그를 찍고 실행되게 만들어 준다.



4. symbolicate

앱이 작동하다 에러로 뻗어버릴때 에러로그는 두가지 방식으로 나온다(난 두개밖에 못봤다)

1. 어떤 메소드가 왜 문제였는지 시스템 로그에 뜸

2. 크래쉬 로그


어떨때 시스템 로그에 보여주고 어떨때 크래쉬 로그인지 잘은 모르겠지만 여튼 대충 저렇다.

첫번째의 경우 문제를 잡아내기 그나마 편리하지만 크래쉬 로그는 사실상 도움이 안된다..(아주 간혹 될때도 있음)

내가 못하는건진 모르겠지만 일반적인 앱이 사용하는 symbolicate 방식으론 이상한 결과만 나오더라.


여튼 그때 쓸 수 있는 ashikase 작품. 시디아에 라이브러리로 있다. https://github.com/ashikase/symbolicate

사실 이 역시 제대로 써보지도 않았고 작동법도 모른다.

tsProtectore 리포트 하기를 누르면 가장 최근의 크래쉬 로그를 symbolicate 로 보내는데 이걸 내 메일로 받아보니 쓸만 하겠더라.


메모리 주소를 메서드 명으로 다 바꿔주는 건 물론, 후킹을 했을 경우도 어떤 트윅이(dylib 파일명이 나옴) 어떤 메서드를 후킹했는지 알 수 있다. 또한 한 메서드를 두개의 트윅이 후킹했다면 각각이 어떤 메서드를 후킹한건지도 나온다.(물론 크래쉬 나기 이전 몇스텝 이내의 작업결과에 한해서.)


요즘엔 개발을 안해서 쓸일이 없지만 하게 된다면, 혹은 버그리포팅을 받을때 유용하게 쓸수 있을듯.

혹은 경우에 따라서 일부로 크래쉬를 내서 후킹할 메서드를 찾는 것도 도움이 될 것 같다;;




이제 나름 상당히 안다 싶었는데 여전히 모르는거, 못하는게 산더미 같이 많은 것 같다..ㅠㅠ

그리고 c 쪽이나 디버깅 같은걸 전무하다 싶을 정도로 모르니...ㅠㅠ

webView 를 얹이고 그 안에 페이지를 띄웠는데 중앙으로 제대로 배치가 안되는 문제가 발생..

(폰 용 페이지를 패드에서도 보는 거라 html 로 만든 테이블뷰가 가운데로 와야 정상임)


난 처음에 뷰 프레임이나 autoresizemask 가 제대로 안잡힌 건줄 알았는데 그게 아니더라..


원인은 meta 태그의 viewport 항목.


width=device-width 이렇게 넘겨주는데 말그대로 device width 다 보니

웹뷰의 크기와는 상관없이 기기의 너비가 반환되어서 들어감.


따라서 사파리라 던가 풀스크린 웹뷰의 경우에는 상관없지만 내가 한것 처럼 화면의 일부분에만 웹뷰를 띄우고

사용할 시에는 전체 너비를 제대로 못 받아 오는 문제가 생겼다.


해결법은 의외로 간단.


webview 의 delegate 지정 후 delegate 에서


- (void)webViewDidFinishLoad:(UIWebView *)webView {

    [webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"document.querySelector('meta[name=viewport]').setAttribute('content', 'width=%d;', false); ", (int)webView.frame.size.width]];

}


이렇게 해주면 된다.

기기의 화면이 회전되는 등 너비 값이 변하였을때도 바로바로 잘 적용됨.

iOS5 기준으로는 http://blog.iolate.kr/113 에서 삽질한 적이 있다.

그런데 이게 iOS6 올라와서 부터는 바뀌었나 보다. 안된다.. ㅋ


iOS5 와 비슷해서 금방 해결은 했지만 여튼 다시 적어본다.

참고로 이 글은 네이버 애플아이폰 까페에 탈옥 먼저 하고 iCloud 백업에서 복원하기 란 글로 먼저 쓰고 다시 옮겨 적는거.


이전 iOS5 때는 쓰다가 백업에서 복원을 원해서였지만 이번엔 목적이 조금 달랐다.

Cydia File system 처리에서 한번 문제가 생겨서 생고생 한적이 있었는데 이번 탈옥이 문제가 있다는 말을 듣고

또 생고생 하긴 싫어서 탈옥 먼저 하고 복원하는게 목적.


스샷은 쓰기 귀찮으니 생략한다. 스샷도 보고 싶으면 위에 아사모 까페에 쓴 글에서 보자.



1. 복원, 새로운 아이폰으로 설정, 애플 아이디 설정은 건너뛰기

2. 바로 탈옥, 시디아 한번 실행

3. 별 문제 없으면 진행. 시디아 스토어는 이용하되, 앱스토어는 이용하지 말 것

4. 뭘 깔든 상관없다. MobileTerminal, iFile, openssh, 파일 시스템을 관리할 수 있는 앱 아무거나 깔아라.

블로그에서 쓰면서 생각해보니 깔거 없이 컴퓨터에서 ifunbox 등으로 바로 지워도 될 듯

5. /var/mobile/Library/Preferences/ 로 이동

com.apple.purplebuddy.plist

com.apple.purple~어쩌구~otbackedup.plist

이거 두개랑

com.apple.facetime~~~

com.apple.imessage~~~

com.apple.imservice~~~ 

로 시작하는 파일들을 다 지워준다

아니. 그냥 이폴더에 있는 설정파일 다 지워줘도 된다.

6. 설정앱 - 일반 - 재설정 - 모든 설정 재설정 클릭

7. 재설정 후 처음 화면이 언어 선택 화면이면 성공! 바로 와이파이 선택이 뜬다면 파일 덜 지운거다.

진행 후 파일 다시 지우고 다시 재설정 하자.

8. 이번엔 iCloud 에서 복원 선택, 애플 아이디 등도 설정

9 끗!

+ Recent posts