블로그 이미지
Every unexpected event is a path to learning for you. blueasa

카테고리

분류 전체보기 (2795)
Unity3D (852)
Programming (478)
Server (33)
Unreal (4)
Gamebryo (56)
Tip & Tech (185)
협업 (61)
3DS Max (3)
Game (12)
Utility (68)
Etc (98)
Link (32)
Portfolio (19)
Subject (90)
iOS,OSX (55)
Android (14)
Linux (5)
잉여 프로젝트 (2)
게임이야기 (3)
Memories (20)
Interest (38)
Thinking (38)
한글 (30)
PaperCraft (5)
Animation (408)
Wallpaper (2)
재테크 (18)
Exercise (3)
나만의 맛집 (3)
냥이 (10)
육아 (16)
Total
Today
Yesterday

아마 국내에서는 4shared같은 사이트보다 토렌트 이용이 압도적으로 많을텐데요. 시놀로지 NAS는 DSM 단계의 Download Station이 토렌트를 지원합니다. 따라서 NAS 자체에서 토렌트를 연결하여 다운로드를 시작하고, 마그넷 연결을 할 수도 있습니다. 어떤식으로든 토렌트가 다운로드 스테이션에 올라가기만하면 그때부터는 스마트폰 또는 컴퓨터를 종료해도 됩니다.

NAS가 없는 경우라면, 속도가 무척 느린 토렌트 파일을 받을 때 PC를 항상 켜둬야하죠. 더군다나 노트북 등으로 이용할라치면 배터리 문제도 생각하지 않을 수 없습니다. 스마트폰에서 토렌트를 받을 수 없으므로 중요한 토렌트 파일을 발견해도 PC가 있는 곳까지 가야만 가능한 상황도 있을 수 있겠습니다. 또 요즘 인기있는 SSD같은 경우에는 쓰기 횟수 제한이 있어 토렌트 사용을 꺼려하는 분위기도 있는데요. 이 모든 것을 시놀로지 NAS로 해결할 수 있습니다. 사실 이 기능 하나만으로도 시놀로지 NAS를 쓸 이유는 충분한 것 같습니다. 무척 유용하거든요!

NAS를 24시간 돌아가도록 설정해두었다면 토렌트도 24시간 이용할 수 있습니다. 인터넷만 연결되어있다면 1년 365일 자동으로 알아서 돌아갑니다. 결국 노트북이나 스마트폰, 그냥 PC에서 토렌트 파일을 NAS에 올려만둔 다음 신경끄고 다음 할 일을 지속할 수 있습니다.

제 글을 처음부터 따라오신 분들이라면 그대로 사용할 수 있는데요. 만약 그렇지않다면 DSM에서 다운로드 스테이션 패키지만 설치해주면 됩니다.

다운로드 스테이션에 토렌트 넣기

여타 다른 NAS 사용법과 마찬가지로 다양하게 토렌트를 이용할 수 있는데요. 다운로드 스테이션을 실행한 후 토렌트를 올려보겠습니다.

이번에 사용할 토렌트 파일은 비트박스 디지(Beatbox DG)와 빈지노(Beenzino)로 이루어진 핫클립(Hotclip)의 믹스테잎입니다. 힙합플레야에서 무료 음원으로 토렌트로 배포되었습니다. (과거에는 이런식으로 토렌트로 무료 음원 배포가 많았는데 요즘에는 사운드 클라우드 등으로 배포가 많이되어 아쉽네요)

가장 쉬운 방법으로는 다운로드 스테이션의 +버튼을 누르고 파일을 선택해주는 것입니다. 이때 다운로드된 파일이 저장될 폴더를 지정할 수 있습니다. 바로 옆에 있는 지구본 모양은 마그넷 연결입니다.



두번째로는 토렌트 파일을 드래그&드랍하여 다운로드 스테이션 위로 올려주는 방식입니다.


세번째 방식은 토렌트가 저장될 특정 폴더를 지정하여 NAS가 알아서 다운로드를 시도하도록 설정하는 방법입니다. 시놀로지 NAS에서는 토렌트 감시라는 표현을 사용하는데요.

다운로드 스테이션 좌측 하단에서 설정을 눌러 들어갑니다.


좌측 메뉴에서 위치로 들어갑니다.

위치에 보면 첫번째에 기본 대상 폴더가 있습니다. 토렌트 다운로드가 완료되어 파일이 저장될 폴더입니다. 저는 download라는 별도의 폴더를 만들어 지정했습니다. 다음으로 토렌트 감시 폴더인데요. 특정 폴더에 토렌트 파일이 있을 경우 자동으로 다운로드를 시작하는 것입니다. 이렇게 지정해두면 시놀로지 DSM이나 다운로드 스테이션을 실행할 필요가 없이 finder에서 곧장 감시 폴더로 접속하여 토렌트 파일을 넣어주기만 하면됩니다. 다운로드 폴더로 지정해도 좋지만 저는 또 다시 별도의 torrent라는 폴더를 만들어 지정해두었습니다.


이제부터는 웹 브라우저로 시놀로지 NAS의 DSM에 접속할 필요없이 파인더에서 NAS에 들어간다음 torrent폴더에 토렌트 파일을 넣어주기만 하면됩니다. 조금전 설정 창에서 체크를 해 두었다면 로드된 토렌트 파일은 NAS가 삭제합니다. 그리고 파일 다운로드는 진행이 되고 100% 완료가되면 지정 폴더에 파일이 생성될 것입니다.


다운로드가 끝나면 지정 폴더에 파일이 생성된 걸 볼 수 있습니다. 토렌트 파일을 다운로드하여 올려주는 것 만으로도 사용자가 할 일은 끝났습니다. 이제 시간되면 컴퓨터 끄고 자면되죠. 똑똑한 시놀로지 NAS가 알아서 계속 다운로드를 해 줄 테니까요. 속도가 엄청 느린 토렌트도 부담없이 켜두면 되니 유용합니다.



출처 : http://namsieon.com/2711

반응형
Posted by blueasa
, |


[링크] http://bulkdisk.tistory.com/88

반응형

'Unity3D > Link' 카테고리의 다른 글

[Link] Visualizer Studio  (0) 2016.06.21
[Link] Unity 3 Audio Spectrum Analysis  (0) 2016.06.21
Unity Cloud Data 소개  (0) 2015.01.20
unity3d grid  (0) 2014.12.19
Tree Pack(FBX)  (0) 2014.09.03
Posted by blueasa
, |

Edit -> Project Settings -> Player 들어가서 


Resolution and Presentation 에서 

Display Resolution dialog 에서 

[Disabled] = 실행시 설정창 비활성화 
[Enabled] = 실행시 설정창 활성화 
[Hidden By Default] = 평소에는 비활성화 Shift 누르면서 프로그램 실행시키면 설정창 활성화 입니다. 

참고 
http://openwiki.kr/unity/class-playersettings




반응형
Posted by blueasa
, |


[링크] http://blog.naver.com/PostList.nhn?blogId=dunkydonk&from=postList&categoryNo=18

반응형
Posted by blueasa
, |



반응형
Posted by blueasa
, |

ios는 상관없지만.. android의 경우 시간을 사용자 임의로 변경할 수 있기 때문에, 시간과 관련하여 컨텐츠의 변경이 필요할 경우 정확한 시간의 정보가 필요함.


이럴때, 미국 국립표준 연구소의 시간을 받아와서 사용하는 방법이 있다.


출처는 - http://stackoverflow.com/questions/6435099/how-to-get-datetime-from-the-internet 요기

실제 수정해서 사용한 코드는 다음과 같음.

TcpClient tcpClient = new TcpClient("time.nist.gov", 13);

StreamReader sr = new StreamReader(tcpClient.GetStream());

        

// 형태 57486 16-04-08 08:53:18 50 0 0 737.0 UTC(NIST) * 

string readData = sr.ReadToEnd();

// 형태 16-04-08 08:57:07

string _time = readData.Substring(readData.IndexOf(" ") + 1, 17);


// 대한민국은 UTC 기준 +9시간.

Datetime currentTime = Convert.ToDateTime(_time).AddHours(9);


// Debug.Log("현재 시간 : " + currentTime.ToString("yyyy-MM-dd HH:mm:ss"));




출처 : http://redccoma.tistory.com/128

반응형

'Unity3D > Script' 카테고리의 다른 글

[펌] OnApplicationFocus 와 OnApplicationPause 차이  (0) 2016.09.22
[펌] CUSTOM COROUTINES(Unity 5.3)  (0) 2016.07.21
[펌] 4. Coroutine 구현에 대해서 공부  (0) 2016.05.11
[펌] Root Motion in Legacy Animation  (0) 2016.03.28
BigNumber  (0) 2016.02.04
Posted by blueasa
, |

I've come across the situation on a number of occasions when coding where I've wanted to convert from a string to an enum. In the Media Catalog sample, I resorted to one giant switch statement that has a case block for each string that returns an enum from it.

One of my colleagues came up with the answer yesterday; it's one of those methods that you can never find when you're looking for it, but once discovered it seems blindingly obvious:

   object Enum.Parse(System.Type enumType, string value, bool ignoreCase);

So you can write the following kind of code:

   enum Colour
   {
      Red,
      Green,
      Blue
   } 

   // ...
   Colour c = (Colour) Enum.Parse(typeof(Colour), "Red", true);
   Console.WriteLine("Colour Value: {0}", c.ToString());

   // Picking an invalid colour throws an ArgumentException. To
   // avoid this, call Enum.IsDefined() first, as follows:
   string nonColour = "Polkadot";

   if (Enum.IsDefined(typeof(Colour), nonColour))
      c = (Colour) Enum.Parse(typeof(Colour), nonColour, true);
   else
      MessageBox.Show("Uh oh!");

What a time saver - thanks, Simon!

Footnote: interestingly, whilst writing this up I noticed that Enum.IsDefined() doesn’t offer the ignoreCase parameter. If you don’t know whether the casing is right, it seems the only way to do the conversion is using the Parse method and catching the ArgumentException. That's not ideal, since it runs a lot slower. I wonder if this is a loophole in the design; no doubt someone like Brad could cast light on it...

posted on Friday, April 02, 2004 1:49 PM

Feedback

# re: How do you convert a string into an enum? 4/2/2004 7:22 PM SBC

You can get the string values of enums also by calling Enum.GetNames or Enum.GetName...




출처 : http://redccoma.tistory.com/117

반응형
Posted by blueasa
, |

가장 처음 만들었던 게임을 만들고 난 후에 가장 아쉬운 부분은 보안적인 처리가 취약했다는거.

(취약이라기 보다는 전무...)

이번 프로젝트를 진행하면서 내 자신이 그래도 어느정도는 만족할 만한 보안처리(클라이언트 기준)를 하고싶었고,
그래서 나온 결과물이

- PlayerPrefs 암호화 (사용자의 임의적인 값 변경을 해도 영향을 받지 않도록)
- 변수 암호화 (메모리 주소 스캔이 어렵도록)
- 클라이언트와 서버간 통신중 주고받는 데이터의 암호화

이중 2개는 처리했고 남은 이슈는 3번째 이슈인데 이것도 내일 아마 처리될듯 하다.

첫번째 암호화에 대해서는 이전 포스팅으로 기록을 남겼고,
이번 포스팅에서는 기본 변수를 어떻게 저장해야 메모리 스캔을 어렵도록 할수 있을까에 대한 포스팅이다.


아는 게 너무 없어서 이것저것 서칭해본 결과 아래의 클래스를 프로젝트에 만들어 두었다.

using System;

using System.Collections;

using System.Security.Cryptography;

using System.Text;


public static class SecureConverter

{

    private static int xorCode = (UnityEngine.Random.Range(0, 10000) + UnityEngine.Random.Range(0, 10000) + UnityEngine.Random.Range(0, 10000)).GetHashCode();

        

    public static int SecureInt(int data)

    {

        return  data ^ xorCode;

    }


    public static string SecureString(string data)

    {

        string newText = "";


        for (int i = 0; i < data.Length; i++)

        {

            int charValue = Convert.ToInt32(data[i]); //get the ASCII value of the character

            charValue ^= xorCode; //xor the value


            newText += char.ConvertFromUtf32(charValue); //convert back to string

        }


        return newText;

    }

}


사용은 아래처럼 저장할 변수와 프로퍼티를 관리하는 스크립트에 만들어 두고 프로퍼티로 접근하면 자동으로 암호화된 값이 저장되고, 불러올때는 복호화해서 불러오기 때문에 원래의 데이터 그대로를 사용할 수 있게 해두었다.

private int _abc;
public int abc { get { return SecureConvert.SecureInt(_abc); } set { _abc = SecureConvert.SecureInt(value); } }

어디서든 abc = 300; 과 같은 형태로 저장하면 실제 암호화된 형태로 저장되기 때문에 원시적인 데이터 검색만으로는 실제 메모리 주소를 찾기가 어렵게 된다.


추신. MD5 나 SHA1 같은 것으로 대체하면 더욱 좋을듯. 이는 추후 포스팅~



출처 : http://redccoma.tistory.com/114

반응형
Posted by blueasa
, |

아무런 처리 없이 PlayerPrefs를 사용할 경우 값이 그대로 노출되면서 접근이 가능하고, 프로그램 밖에서 값을 수정할 경우 수정된 값 그대로 프로그램에 적용되는 문제점이 있음.


그런고로 1차적으로 어느정도는 암호화해야 하는데..구글링 한 결과 아주 만족스럽지는 않지만 적어도 원하지 않는 값으로 프로그램에 적용되는 것을 막아주도록 작성된 내용을 유니티포럼에서 찾아 포스팅한다..

(출처 - http://forum.unity3d.com/threads/playerprefs-encryption.26437/)


아래 코드의 포인트는 테스트해본 결과 실제 저장되는 PlayerPrefs의 값은 원본 그대로 저장된다. 노출자체는 된다는 얘기지. 다만, 직접 해당 유저가 해당 값을 수정하면 CheckEncryption함수를 통과하지 못해 DEFAULT 값으로 처리되면서, 기존에 저장되어 있던 PlayerPrefs의 해당 키(3개)는 모두 삭제처리된다.


using UnityEngine;

using System.Collections;

using System.Security.Cryptography;

using System.Text;

 

public class EncryptedPlayerPrefs  {

 

    // Encrypted PlayerPrefs

    // Written by Sven Magnus

    // MD5 code by Matthew Wegner (from [url]http://www.unifycommunity.com/wiki/index.php?title=MD5[/url])

    

    

    // Modify this key in this file :

    private static string privateKey="9ETrEsWaFRach3gexaDr";

    

    // Add some values to this array before using EncryptedPlayerPrefs

    public static string[] keys;

    

    

    public static string Md5(string strToEncrypt) {

        UTF8Encoding ue = new UTF8Encoding();

        byte[] bytes = ue.GetBytes(strToEncrypt);

 

        MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();

        byte[] hashBytes = md5.ComputeHash(bytes);

 

        string hashString = "";

 

        for (int i = 0; i < hashBytes.Length; i++) {

            hashString += System.Convert.ToString(hashBytes[i], 16).PadLeft(2, '0');

        }

 

        return hashString.PadLeft(32, '0');

    }

    

    public static void SaveEncryption(string key, string type, string value) {

        int keyIndex = (int)Mathf.Floor(Random.value * keys.Length);

        string secretKey = keys[keyIndex];

        string check = Md5(type + "_" + privateKey + "_" + secretKey + "_" + value);

        PlayerPrefs.SetString(key + "_encryption_check", check);

        PlayerPrefs.SetInt(key + "_used_key", keyIndex);

    }

    

    public static bool CheckEncryption(string key, string type, string value) {

        int keyIndex = PlayerPrefs.GetInt(key + "_used_key");

        string secretKey = keys[keyIndex];

        string check = Md5(type + "_" + privateKey + "_" + secretKey + "_" + value);

        if(!PlayerPrefs.HasKey(key + "_encryption_check")) return false;

        string storedCheck = PlayerPrefs.GetString(key + "_encryption_check");

        return storedCheck == check;

    }

    

    public static void SetInt(string key, int value) {

        PlayerPrefs.SetInt(key, value);

        SaveEncryption(key, "int", value.ToString());

    }

    

    public static void SetFloat(string key, float value) {

        PlayerPrefs.SetFloat(key, value);

        SaveEncryption(key, "float", Mathf.Floor(value*1000).ToString());

    }

    

    public static void SetString(string key, string value) {

        PlayerPrefs.SetString(key, value);

        SaveEncryption(key, "string", value);

    }

    

    public static int GetInt(string key) {

        return GetInt(key, 0);

    }

    

    public static float GetFloat(string key) {

        return GetFloat(key, 0f);

    }

    

    public static string GetString(string key) {

        return GetString(key, "");

    }

    

    public static int GetInt(string key,int defaultValue) {

        int value = PlayerPrefs.GetInt(key);

        if(!CheckEncryption(key, "int", value.ToString())) return defaultValue;

        return value;

    }

    

    public static float GetFloat(string key, float defaultValue) {

        float value = PlayerPrefs.GetFloat(key);

        if(!CheckEncryption(key, "float", Mathf.Floor(value*1000).ToString())) return defaultValue;

        return value;

    }

    

    public static string GetString(string key, string defaultValue) {

        string value = PlayerPrefs.GetString(key);

        if(!CheckEncryption(key, "string", value)) return defaultValue;

        return value;

    }

    

    public static bool HasKey(string key) {

        return PlayerPrefs.HasKey(key);

    }

    

    public static void DeleteKey(string key) {

        PlayerPrefs.DeleteKey(key);

        PlayerPrefs.DeleteKey(key + "_encryption_check");

        PlayerPrefs.DeleteKey(key + "_used_key");

    }

    

}


사용법은 PlayerPrefs의 사용법과 동일하다. (아래의 암호화를 위한 키를 추가한 후 사용하면 된다.) 

  EncryptedPlayerPrefs.keys=new string[5];


        EncryptedPlayerPrefs.keys[0]="23Wrudre";

        EncryptedPlayerPrefs.keys[1]="SP9DupHa";

        EncryptedPlayerPrefs.keys[2]="frA5rAS3";

        EncryptedPlayerPrefs.keys[3]="tHat2epr";

        EncryptedPlayerPrefs.keys[4]="jaw3eDAs";

사용시 PlayerPrefs 클래스 대신 EncryptedPlayerPrefs을 사용하면 된다. 키값 전부 지워주는 것은 기존대로 PlayerPrefs꺼 가져다가 쓰면 됨. 추후 빌드시 난독화 과정을 거치면 어느정도 보안처리를 했다고 볼수 있겠지. 


---- 10월 27일 추가.


위의 클래스를 사용하면 값이 그대로 보이기때문에, 이러한 문제를 해결하기위해서는 PlayerPrefs를 약간 가공해서 쓰는것도 한가지 방법이다.

특정 시크릿키를 사용해 Int일 경우 String으로 변환해서 변환된 문자열을 암호화하여 PlayerPrefs.SetString으로 저장하고 불러올때는 복호화 후 Convert 등을 이용해 다시 int 로 바꾸어 호출해 사용하는 방법이 좋아보인다.


이와 관련하여 암/복호화를 특정키를 사용하여 쉽게 할 수 있도록 하는 클래스는 검색하면 어느정도 나오니 그것을 이용해 구현하는 것이 적합.


---- 2015.06.17

http://ikpil.com/1342



출처 : http://redccoma.tistory.com/113

반응형
Posted by blueasa
, |

Android 나 PC 의 유니티에서 WWW 를 통해 파일을 받을 경우 IOS 는 해당 컨텐츠 헤더에 있는 값으로 자동으로 캐싱을 진행해 준다.

너무나 완벽한 OS 라서 문제가 생긴다..


아래 두가지 경우의 파일이 있다.



< Cache-Control 이 설정되어 있는 경우 >



< Cache-Control 이 없는 경우 >



Cache-Control 이 있는경우 IOS 에서는 해당 파일 캐싱을 진짜로 구현해 준다. ( 원래 이게 당연한 거지만.. )

따라서 저 만료 날자가 되기 전에 다시 같은 주소로 요청을 하면 새로 받아오지 않고 이전 캐싱된 데이터를 준다.


이 경우 가장 간단하게 해결하는 방법은 주소뒤에 의미없는 값을 추가하여 캐싱되지 않는 것처럼 꾸미는 것이다.

WWW( "http://www.naver.com/file.json?t=213948712" );

그러나 이 경우 클라이언트나 CDN 등에 쓸데없는 캐싱이 생길 수 있으며, 깔끔하지 않다.


가능한 Request 에서 요청 헤더에 다음과 같이 캐싱을 하지 않겠다고 추가하는것이 좋다.

WWWForm form = new WWWForm();

form.AddField( "Cache-Control", "no-cache" );




출처 : http://flystone.tistory.com/195

반응형
Posted by blueasa
, |