로그인

검색

IT
2009.02.10 16:14

플래시 html간의 통신

조회 수 1328 추천 수 0 댓글 0
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 게시글 수정 내역 댓글로 가기 인쇄
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 게시글 수정 내역 댓글로 가기 인쇄

 출처 : http://blog.daum.net/queenyjina/7553390

 
플래시와 HTML 그리고 Javascript 간의 통신에는 여러가지가 사용됩니다.

일단 HTML에서 플래시로 데이터를 넘기는 것에는 <object>태그와 <embed> 태그의 플래시 파일명에 변수를 넣는 방법과 flashVars 변수로 플래시에 데이터를 전달하는 방법이 있습니다.

Javascript와의 통신에는 SetVariable과 GetVariable 그리고 Object.watch()를 통한 실시간 리스너 구현 및 요즘에는 ExternalInterface로 통신을 합니다.

HTML부터 알아보겠습니다.

 

HTML과의 통신#

 

<object>,<embed> 태그 개념정리#

참고 : http://korea.internet.com/channel/content.asp?nid=21907&cid=187#start

<OBJECT> 태그#

object element 는 문서내에 플래시나 동영상과 같은 개체(Object)를 삽입하는데 사용됩니다.

HTML 태그 문서에 개체를 삽입하는 태그는 여러가지가 있습니다. 동영상과 음악과 같은 멀티미디어를 삽입하는 embed, 자바 애플릿을 삽입하는 applet!! 엘리먼트 등이 있습니다. 최근의 추세는 object 엘리먼트로 통합되는 방향입니다.

 

  • 문맥
    OBJECT는 인라인 요소이다.
  • 포함 내용
    PARAM 요소를 포함할 수 있고 객체 그 자체로 제대로 표현할 수 없는 경우에 한하여 포함된 다른 요소들로 그 객체를 표현하는 데 도움을 줄 수 있다. 이러한 경우가 아닌 경우에는 포함된 요소들을 무시한다. 다수의 OBJECT 요소를 중첩하여 사용할 수 있다.

따라서 <embed> 태그는 <object></object> 태그 안에 기술되며 <object>가 표현되지 않을 경우 <embed>태그가 사용된다.

  • 태그 사용
    시작 태그와 끝 태그 모두 필요하다.

 

- 속성에 대한 자세한 사항은 참고URL을 참고

 

<OBJECT> 태그의 <param>요소#

객체를 설명해주는 대체 내용 뿐만 아니라 OBJECT 요소는 다수의 PARAM 요소를 포함할 수 있다. 이 요소는 삽입된 프로그램이나 애플릿에 대하여 필요한 인자 정보를 제공하기 위하여 사용된다. 인자의 구체적인 값이나 형식들은 삽입한 객체에 따라 다르게 필요하다. 자바 애플릿의 경우 많은 인자값을 가지게 되는데 예를 들어 음악 파일을 연주하는 자바 애플릿은 음악 파일의 URI를 알려주기 위한 파라미터 값을 가지게 된다.

PARAM 요소는 작동 프로그램에 전달하는 값들이다.

 

PARAM 요소의 특징

  • 문맥
        OBJECT와 APPLET! 요소 안에서만 사용될 수 있다.
  • 포함 내용
        공백 구성 요소(포함하는 요소가 없다.)
  • 태그 사용
        공백 구성 요소로 시작 태그만 필요하고 끝 태그는 사용할 수 없다.

PARAM 요소의 속성

  • name(텍스트)
        인자의 이름을 명시
  • value(텍스트)
        인자의 값을 명시한다.
  • valuetype(값 형식 : value type)
        지정된 값의 형식을 지정한다. 지정된 값이 텍스트 형태의 데이터인 경우에는     data라는 값을 사용하고 지정된 값이 URI라면 ref값을 사용한다. 그리고 문서에     있는 다른 OBJECT 요소에 대한 포인터 값인 경우에는 object값을 사용한다. 이     값의 세부 사항은 사용한 객체의 형식에 따라 달라진다.
  • type(내용 형식값 : content type)
        valuetype의 값이ref라면 인자 값에 의해 명시된 자원에 대한 마임 타입(MIME type) 값을 지정하게 된다.

 

<EMBED> 태그#

참조 : embed 태그에 대한 모든것

 

<EMBED> ALIGN, ALT,BORDER, HSPACE, NAME, PALETTE, PLUGINSPACE, VSPAC0E
이것은 html문서에 외부화일을 연결할 때에 사용한다.
<EMBED SRC="song.mid" WIDTH="100" HEIGHT="50">
위의 보기는 song.mid가 연주되도록 하는데, 브라우저상에 제어판이 그림으로 나타난다. 물론, 브라우저에 midi음악을 연주할 프로그램이 plug-in 되어 있음을 전제로 한다.
  
PALETTE = foreground, background
사용자의 컴퓨터가 256 색으로 설정되어 있을 경우, 색상이 그릇되게 나타나는 palette flash라는 현상이 나타날 수 있다. 이것을 피하기 위해 foreground나 background palette를 사용한다. 그런데, 이것은 Windows platform에서만 가능하다.
 
PLUGINSPACE = "주소"
이것은 사용자가 해당 파일을 실행할 plug-in이 없을 경우, 그것을 얻을 수 있는 주소를 설정하여 설치할 수 있도록 돕는 데에 사용한다.

 

참조  URL에 보면 이런 글이 있다.

embed 태그 뒤에 붙이는 여러 속성들은 당연히 미디어플레이어 오브젝트의 속성들을 붙여주면 되는거죠. ^^
미디어플레이어의 속성들은 MSDN(Microsoft Developed Netword)을 참고 하시면 됩니다.

이게 무엇을 뜻하는 걸까? 미디어 플레이어의 속성을 <embed> 태그에 속성으로 넣어주면 작동시 참고한다는 말인데... 그렇다면 기타 다른 오브젝트인 플래시 같은 것도 플래시 플레이어의 속성을 넣어주면 된다는 내용이다. 플래시 플레이어의 속성은 adobe 사이트가서 보면 될 것이고...

왜 <object>와 <embed> 태그에 알 수도 없는 속성들이 붙는지 잘 몰랐는데... 삽입되는 오브젝트를 플레이(작동)시키는 프로그램에 전달하는 값이라고 생각하면 되겠군...

어떻게 html에서 플래시로 값을 넘길 수 있는지가 의문이었고, 플래시만을 위한 태그를 html에 넣었다는게 좀 말이 안된다 싶었는데 오브젝트 태그들은 html과 독립직으로 프로그램들과 값을 주고 받는 속성을 사용할 수 있는 것이다.

그래서 그 전달하는 값에 플래시로 보내는 파라미터를 넣으면 플래시 플레이어가 인식을 할 수 있는 것이었다. 플래시 플레이어에서 새로운 기능이 있으면 html은 상관없이 플래이어만 업그레이드 하고 속성으로 값을 전달 받으면 되는 것이다. ExternalInterface와 FlashVars가 추가된 것도 이렇게 이해할 수 있다.

 

embed 와 object 의 차이점#

embed 엘리먼트는 개채삽입으로 자신의 컴퓨터에 해당 미디어파일을 실행할수 있는 프로그램이 없다면 실행이 되지 않습니다. 그러나 object 엘리먼트는 웹에서 개채를 로드해서 재생되므로 프로그램이 없어도 실행이 가능합니다.

HTML 페이지에 멀티미디어를 추가하는데 embed 엘리먼트도 사용할 수 있지만 embed 엘리먼트를 사용하면 보다 다양한 미디어를 사용 가능합니다.

 

embed 와 object 의 작성법 (플래시 객체 삽입시)#

 

<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=8,0,0,0" width="550"  height="400" id="test" align="middle">

<param name="allowScriptAccess" value="sameDomain" />

<param name="movie" value="test.swf" />

<param name="quality" value="high" />

<param name="bgcolor" value="#ffffff" />

<embed src="test.swf" quality="high" bgcolor="#ffffff" width="550" height="400" name="test" align="middle" allowScriptAccess="sameDomain" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" />

</object>

특이한 점은 <object>태그는 태그자체의 속성과 실행될 프로그램에 전달할 속성, 즉 <param>을 따로 작성하지만 <embed>는 속성으로 모두 다 기술한다는 점이다.

그리고 <object>태그 안에 <embed> 태그를 작성해서 <object>속성이 작동하지 않을 경우 <embed> 태그가 실행 되도록 하고 있다.

 

플래시와 연동을 위한 <object>,<embed> 활용방법#

swf파일 주소 끝 부분에 ?로 변수를 넣어주면 된다.

<object>

<param name='movie' value='flash.swf?variable=value&variable2=value2&variable3=value3'/>

<embed>

<embed src="flash.swf?variable=value&variable2=value2&variable3=value3">

<object>태그는 <param> 태그의 주소부분이 넣어주고 <embed>태그는 주소속성에 넣어준다. 이렇게 사용하면 플래시에서는 variable이라는 변수로 value라는 데이터를 참조할 수 있다.

 

FlashVars를 이용한 변수전달 방법#

새로 생긴 변수 전달방법으로 플래시 주소 뒤에 변수를 쓰지 않고 플래시 플레이어에 전달하는 FlashVars라는 속성에 변수를 담아서 전달하는 경우이다.

FlashVars를 사용하는 이유는 플래시 파일명 뒤에 변수를 전달하면 똑같은 파일이라도 변수가 다르기 때문에 플래시 파일을 다시 다운로드 한다.

하지만 전달하는 값만 다르고 플레이 파일을 똑같은 경우는 매 페이지마다 계속 플래시 파일을 다운 받아야 하기 때문에 비효율적이지만 FlashVars를 사용하면 변수가 달라지더라도 파일명은 같기 때문에 한번 다운로드한 플래시 파일은 다시 다운받지 않기 때문에 더 효율적인 방식이다.
(개발과정에서 테스트시에는 더 귀찮을 수도 있다. 파일명이 같기 때문에 새로 업데이트한 파일을 받지 않아서 적용된 상태를 볼 수가 없기 때문이다. 이럴때는 예전 방식인파일명뒤에 변수전달 방식을 사용하고 변수에는 자바스크립트로 랜덤 값을 주면 페이지 새로고침시 마다 매번 파일을 다운 받게 만들 수 있다.)

 

FlashVars 사용법#

FlashVars라는 속성을 추가해준다.

<object>

<param name="FlashVars" value="username=Thomas" />

<embed>

<embed src="flashvars.swf" FlashVars="username=Thomas" quality="high" bgcolor="#ffffff" width="550" height="400" name="flashvars" align="middle" allowScriptAccess="sameDomain" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" />

object는 따로 FlashVars 태그를 만들어 사용하고 embed에는 FlashVars라는 속성을 추가한다.

 

여러개의 변수를 전달하는 방법은 동일하게 &를 사용한다.

 

 

Javascript와의 통신#

HTML에서 플래시 플레이어에 대한 스크립트 허용 또는 거부하는 속성인 allowScriptAccess를 설정

IE : <param name="allowScriptAccess" value="sameDomain" />

FF : <embed allowScriptAccess="sameDomain"> - <embed> 태그 속성에 추가

 

getURL로 자바스크립트 호출하기

getURL("javascript:myfunction('" + parameter + "')");

myfunction에 자스의 함수명을 넣고 parameter에 전달할 값을 넣는다.

 

SetVariable로 자바스크립트에서 플래시로변수 전달하기

문법

window.document.flashID.SetVariable(변수명:String, 값:String);

flashID에 html에 작성된 플래시 객체에 대한 name과 ID의 값을 넣고 변수명과 값을 넣으면 됩니다.

하지만 document는 IE의 객체이기 때문에 FF에서는 동작은 안합니다. 그리고 IE에서 사용시 로컬에서 접근하면 보안상 접근을 막기 때문에 서버에 올려야 테스트가 가능합니다. 또한 변수의 로딩 시점 때문에 플래시에서 변수가 들어올 때까지 확인을 해야합니다.

 

SetVariable은 변수명에서 변수나 객체로 접근해서 값을 넣을 수 있다.

window.document.flashID.SetVariable(변수명.속성:String,:String);

 

GetVariable로 자바스크립트에서 플래시의 변수값 알아오기

문법

window.document.flashID.GetVariable(변수명:String);

객체의 속성이나 변수를 얻어올 때 사용함.

변수명만 있다 - 값은 없다.

 

Object.watch()를 이용하여 외부변수 로딩시점 알아내기

 

Object.watch()의 사용방법

Object.watch()는 오브젝트의 속성을 감시하는 매서드로써, 속성값이 변경되면 지정한 콜백함수를 실행함니다

Object.watch()는 Object에서 상속받은 속성으로 범용으로 사용가능합니다.

속성값이 변경되었는지를 검사하는 함수로, 주의할 점은, _x, _y, _width, _height 등의 미리 정의된 ActionScript 속성은 getter/setter 속성이므로 Object.watch()로 감시할 수 없습니다.

 

문법

Object.watch("감시할 속성 이름", 값이 바뀌었을 때 실행할 콜백 함수, [전달 매개변수 : 선택사항])

콜백 함수를 작성할 때 4개의 파라미터를 사용가능합니다. 파라미터의 내용은 위에 표기 된 대로 입니다.

callBack = function(바뀐 속성 이름, 바뀌기전의 값, 바뀐후의 값, watch() 세번째 매개변수){ code... }

함수에 작성된 네개의 매개변수중 앞의 세개는 자동 전달 되고 네번째만 사용자가 정의 할 수 있습니다.

바로 Object.watch() 호출시 전달하는 파라미터 값중 세번째 값이 콜백함수의 네번째 매개변수로 전달이 되는 것입니다. 단 전달 매개변수는 단 하나만 전달 할 수 있습니다.

 

callback 메서드 정의에서 return 문을 사용하여 감시하고 있는 속성 값에 영향을 줄 수 있습니다. callback 메서드에 의해 반환되는 값은 감시된 객체 속성에 지정됩니다. 속성을 모니터링하는지, 수정하는지, 아니면 변경할 수 없게 하는지 여부에 따라서 반환되는 값이 달라집니다.

callBack = function(감시하는 속성 이름, 바뀌기전의 값, 바뀐후의 값, watch() 세번째 매개변수){ // return 없음 }
callBack = function(감시하는 속성 이름, 바뀌기전의 값, 바뀐후의 값, watch() 세번째 매개변수){ return 바뀐 후의 값 }
callBack = function(감시하는 속성 이름, 바뀌기전의 값, 바뀐후의 값, watch() 세번째 매개변수){ return 고유의 값 }
callBack = function(감시하는 속성 이름, 바뀌기전의 값, 바뀐후의 값, watch() 세번째 매개변수){ return 바뀌기 전의 값 }

 

  • 첫번째, 리턴 값이 없는 경우 감시하는 속성에는 undefined가 지정됩니다.
  • 두번째, 단순히 속성을 모니터링하는 경우 newVal 매개 변수가 반환됩니다.
  • 세번째, 속성 값을 수정하는 경우 고유한 값이 반환됩니다.
  • 네번째, 속성을 변경할 수 없게 하려는 경우 oldVal 매개 변수가 반환됩니다.

 

Object.watch()의 장점

리소스를 거의 잡지 않고, 리스너 역할을 할 수 있다

Object.watch()로 해당 데이터를 걸어두게 되면 감시자 역할을 해서 특정 값이 변할때단 한번 이벤트가 발생됩니다.

ExternalInterface는 플래시와 자바스크립트 통신을 위해 필요한 인터페이스지만 플래시 자체 내에서 변화를 감지하지 못하기 때문에 한계점이 있음.

 

예) SetVariable 등으로 변수를 보낼 때 변수를 Object.watch()로 걸어두면 변수가 들어온 시점을 찾기 위해 onEnterFrame, setInterval, getTimer 등을 사용할 필요없이 변수가 들어왔을 때 함수를 실행 할 수 있음...

 

 

fscommand를 사용하여 자바스크립트의 함수호출하기

fscommand 전역함수로 VBscript! 및 Javascript와 통신할 수 있습니다.

통신을 위해서는 html의 태그를 다음과 같이 'always'로 설정해야 합니다.

<param name="allowScriptAccess" value="always" />

<embed allowScriptAccess="always">

 

플래시에서

fscommand(command:String, parameters:String) : Void

command : 플래시에서 외부로 전달하는 명령어

parameters : 플래시에서 외부로 전달하는 매개변수

 

html에서 - 자바스크립트

test_DoFSCommand = function(command, args){ code... }

html에서 - VB스크립트

Sub test_FSCommand(ByVal command, ByVal args)

code..
.

end
sub

DoFSCommand는 자바스크립트에 존재하는 메서드이며, html에서 플래시 삽입시 사용된 id에 "_"+DoFSCommand를 붙여준 형태입니다.

 

tip - 제작설정의 템플릿을 "Flash에서 FSCommand 사용하기"로 설정하면 제작시에 html에 자동으로 자바스크립트를 생성해 줍니다.

 

fscommand의 장점

getURL을 사용하지 않고 자바스크립트로 플래시 데이터 전달 가능

 

 

ExternalInterface을 사용하여 외부 데이터 주고, 받기

ExternalInterface 클래스는 ActionScript와 Flash Player 컨테이너(예: JavaScript HTML 페이지 또는 Flash Player를 포함한 데스크톱 응용 프로그램) 사이의 직접 통신을 가능하게 하는 외부 API(응용 프로그래밍 인터페이스)입니다.

ExternalInterface의 기능은 fscommand(), CallFrame()CallLabel() 메서드와 비슷하지만 보다 유연하고 보다 일반적인 적용이 가능합니다. JavaScript-ActionScript 통신에는 ExternalInterface를 사용하는 것이 좋습니다.

ActionScript에서 HTML 페이지의 모든 JavaScript 함수를 호출하여 모든 데이터 유형의 인수를 수 제한 없이 전달하고 호출에서 반환값을 받을 수 있습니다.

HTML 페이지의 JavaScript에서 Flash Player의 ActionScript 함수를 호출할 수 있습니다. ActionScript 함수는 값을 반환할 수 있고 JavaScript는 호출의 반환값을 즉시 수신합니다.

 

외부의 인터페이스와 통신하기 위해 사용되는 API입니다.

fscommand 등을 사용하지 안혹도 자바스크립트와 통신이 가능합니다.

getURL을 사용하지 않고도 자바스크립트 함수를 호출할 수 있으며, 자바스크립트에서 플래시 함수를 호출할 수 있습니다.

두개의 메서드와 하나의 속성이 있는데 모두 static 이므로 반드시 클래스 명을 통해 접근해야 합니다.

 

사용하기 전에 외부 클래스를 불러와야 합니다.

import! flash.external.*;

 

결론적으로 플래시에서 자바스크립트를 호출하려면 call()로 자바스크립트 함수를 호출하고

자바스크립트에서 호출하려면 플래시에서 addCallback으로 플래시 내의 함수를 등록해 놓으면 자바스크립트에서 호출이 가능한 것이다.

 

메서드

addCallback(methodName:String, instance:Object, method:Function) : Boolean

컨테이너로부터 호출 가능하도록 ActionScript 메서드를 등록합니다. addCallBack()이 성공적으로 호출된 후에는 Flash Player에 등록된 함수를 컨테이너의 JavaScript 또는 ActiveX 코드를 사용하여 호출할 수 있습니다.

 

매개 변수

methodName:String - JavaScript에서 ActionScript 함수가 호출되는 이름입니다. 이 이름은 실제 ActionScript 메서드 이름과 일치할 필요는 없습니다.

instance:Object - 메서드에서 this가 확인하는 객체입니다. 이 객체는 해당 메서드를 찾을 수 있는 객체일 필요는 없으며, 객체 또는 null을 지정할 수 있습니다.

method:Function - JavaScript에서 호출되는 ActionScript 메서드입니다.

 

call(methodName:String, [parameter1:Object]) : Object

0개 이상의 인수를 전달하는 Flash Player 컨테이너에 의해 노출된 함수를 호출합니다. 원하는 함수가 없으면 호출은 null을 반환하고, 그렇지 않으면 함수가 제공하는 값을 반환합니다. 반복은 허용되지 않으며, 반복 호출은 null 응답을 생성합니다.

컨테이너가 HTML 페이지이면 이 메서드는 <script> 요소에서 JavaScript 함수를 호출합니다.

컨테이너가 다른 ActiveX 컨테이너일 경우 이 메서드는 지정된 이름으로 이벤트를 브로드캐스트하고 컨테이너는 이벤트를 처리합니다.

 

매개 변수

methodName:String - 컨테이너에서 호출될 함수의 이름입니다. 이 함수가 매개 변수를 허용하면 methodName 매개 변수 뒤에 나타나야 합니다.

parameter1:Object [선택 사항] - 함수에 전달할 모든 매개 변수입니다. 0개 이상의 매개 변수를 쉼표로 구분하여 지정할 수 있습니다. 이러한 매개 변수는 어떤 ActionScript 데이터 유형이나 가능합니다. JavaScript 함수에 대한 호출일 경우 ActionScript 유형은 자동적으로 JavaScript 유형으로 마샬링되며, 다른 ActiveX 컨테이너에 대한 호출일 경우 매개 변수는 요청 메시지로 인코딩됩니다.

 

 

크로스도메인

도메인이 서로 다른 파일끼리 통신하여 데이터를 주고받아야 할 때. 플래시 보안정책상 통신할 수 없는 경우를 가능하게 만들어 줍니다.

 

Flash 문서가 다른 도메인의 데이터에 액세스하려고 시도하면 Flash Player는 자동적으로 그 도메인에서 정책 파일을 로드합니다. 액세스하려는 Flash 문서의 도메인이 정책 파일에 포함되어 있으면 자동적으로 데이터에 액세스할 수 있게 됩니다.

정책 파일의 이름은 반드시 crossdomain.xml이어야 합니다. 정책 파일은 루트 디렉토리에 저장되거나, 일부 ActionScript가 추가되는 경우 해당 데이터를 제공하는 서버의 다른 디렉토리에 저장할 수 있습니다. 자세한 내용은 사용자 정의 정책 파일 위치을(를) 참조하십시오. 정책 파일은 HTTP, HTTPS 또는 FTP상에서 통신하는 서버에서만 동작합니다. 정책 파일은 파일이 저장된 서버의 포트와 프로토콜에만 해당됩니다.

 

xml파일의 내용은 다음과 같습니다.

<?xml version="1.0"?>

<!-- http://www.foo.com/crossdomain.xml -->

<cross-domain-policy>

<allow-access-from domain="www.friendOfFoo.com" />

<allow-access-from domain="*.foo.com" />

<allow-access-from domain="105.216.0.40" />

</cross-domain-policy>

 

?

List of Articles
번호 분류 제목 글쓴이 날짜 조회 수
22 IT 구글 북 스캔 기계의 비밀을 파헤친다. 모아레 2009.05.11 1279
21 IT 무선 인터넷 보안팁 10가지 모아레 2009.04.27 1354
20 IT 텍스트큐브 관리자로그인 관련 모아레 2009.03.22 593
19 IT 탐색기에서 보기 기본설정을 아이콘으로 바꾸는 방법 모아레 2009.03.13 761
» IT 플래시 html간의 통신 모아레 2009.02.10 1328
17 IT 노트북 배터리에 대한 모든 것 (스크롤 압박 주의) 모아레 2009.02.07 3255
16 IT 애플 vs. 팜 특허전쟁 심층분석 모아레 2009.02.06 905
15 IT 윈도우 XP에서 137GB가 넘는 용량의 하드디스크를 인식 못하는 경우 모아레 2009.01.19 1304
14 IT 베가스 강좌 모아레 2008.07.17 1499
13 IT 플래시 강좌 모아레 2008.07.11 860
12 IT 플래시 3.0 모아레 2008.05.14 785
11 IT 리눅스를 처음 사용하시는 분들을 위한 북마크 모아레 2008.05.12 1492
10 IT 공유기 문제 관련 모아레 2008.03.11 3406
9 IT 자기 컴퓨터에 테터툴즈 설치하기 MoA 2007.08.26 1443
8 IT XP Secrets MoA 2007.06.21 1050
7 IT 컴퓨터 관련 사이트 정리 MoA 2007.05.14 1434
6 IT 홈페이지 방문자 알기? MoA 2007.05.04 1549
5 IT 플래시 주의할사항, 중요한 점 요약 MoA 2006.08.14 1335
4 IT 함수포인터 MoA 2006.12.11 1783
3 IT 플래시 폰트 임베드하는법 MoA 2006.08.24 1357
Board Pagination Prev 1 ... 4 5 6 7 8 9 10 Next
/ 10