Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #==============================================================================
- # ** FTP
- #==============================================================================
- class FTP
- #--------------------------------------------------------------------------
- # * 서버
- #--------------------------------------------------------------------------
- HOST = '112.175.184.88'
- PORT = 21
- #--------------------------------------------------------------------------
- # * 정보
- #--------------------------------------------------------------------------
- USER = 'anonymous'
- PASS = 'anonymous@'
- #--------------------------------------------------------------------------
- # * 클래스 변수
- #--------------------------------------------------------------------------
- @@list = []
- #--------------------------------------------------------------------------
- # * 셀프 클래스
- #--------------------------------------------------------------------------
- class << self
- #----------------------------------------------------------------------
- # * 다운로드
- #----------------------------------------------------------------------
- def download(filename, path = "")
- @@list.push([new, sprintf("download %s %s", filename, path)])
- end
- #----------------------------------------------------------------------
- # * 읽기
- #----------------------------------------------------------------------
- def read(filename)
- @@list.push([new, sprintf("read %s", filename)])
- end
- #----------------------------------------------------------------------
- # * 업로드
- #----------------------------------------------------------------------
- def upload(filename, toname = "")
- @@list.push([new, sprintf("upload %s %s", filename, toname)])
- end
- #----------------------------------------------------------------------
- # * 갱신
- #----------------------------------------------------------------------
- def update
- unless @@list[0].nil?
- unless @@list[0][0].sock
- @@list.delete_at(0)
- return
- end
- if @@list[0][0].port
- case @@list[0][1]
- when %r(download (.*) (.*))
- @@list[0][0].download($1, $2)
- @@list[0][1] = nil
- when %r(read (.*))
- @@list[0][0].read($1)
- @@list[0][1] = nil
- when %r(upload (.*) (.*))
- @@list[0][0].upload($1, $2)
- @@list[0][1] = nil
- end
- end
- @@list[0][0].update
- end
- end
- #----------------------------------------------------------------------
- # * 닫기
- #----------------------------------------------------------------------
- def close
- @@list.each_index do |i|
- @@list[i][0].close
- @@list.delete_at(i)
- end
- end
- #----------------------------------------------------------------------
- # * 사용중
- #----------------------------------------------------------------------
- def in_use?
- @@list != []
- end
- #----------------------------------------------------------------------
- # * 데이터
- #----------------------------------------------------------------------
- def data
- @@list[0][0] if in_use?
- end
- end
- #--------------------------------------------------------------------------
- # * 동적 링크 라이브러리
- #--------------------------------------------------------------------------
- DLL = 'ws2_32'
- #--------------------------------------------------------------------------
- # * Ws2_32
- #--------------------------------------------------------------------------
- IOCTLSOCKET = Win32API.new(DLL, 'ioctlsocket', 'plp', 'l')
- CLOSESOCKET = Win32API.new(DLL, 'closesocket', 'p', 'l')
- CONNECT = Win32API.new(DLL, 'connect', 'ppl', 'l')
- GETHOSTBYNAME = Win32API.new(DLL, 'gethostbyname', 'p', 'l')
- RECV = Win32API.new(DLL, 'recv', 'ppll', 'l')
- SELECT = Win32API.new(DLL, 'select', 'lpppp', 'l')
- SEND = Win32API.new(DLL, 'send', 'ppll', 'l')
- SOCKET = Win32API.new(DLL, 'socket', 'lll', 'l')
- WSAGETLASTERROR = Win32API.new(DLL, 'WSAGetLastError', '', 'l')
- #--------------------------------------------------------------------------
- # * 공개 인스턴스 변수
- #--------------------------------------------------------------------------
- attr_reader :sock, :host, :port
- #--------------------------------------------------------------------------
- # * 초기화
- #--------------------------------------------------------------------------
- def initialize
- join
- end
- #--------------------------------------------------------------------------
- # * 접속
- #--------------------------------------------------------------------------
- def join
- return unless @sock.nil?
- @sock = socket(2, 1, 6)
- error if @sock == -1
- ioctlsocket(0x8004667e, 1)
- sockaddr = sockaddr_in(HOST, PORT)
- connect(sockaddr); sleep(0.1)
- send(sprintf('USER %s', USER))
- send(sprintf('PASS %s', PASS))
- end
- #--------------------------------------------------------------------------
- # * 다운로드
- #--------------------------------------------------------------------------
- def download(filename, path)
- send('TYPE I')
- @file = path
- send(sprintf('RETR %s', filename))
- filename
- end
- #--------------------------------------------------------------------------
- # * 읽기
- #--------------------------------------------------------------------------
- def read(filename)
- send('TYPE I')
- @read = filename
- @file = filename
- send(sprintf('RETR %s', filename))
- filename
- end
- #--------------------------------------------------------------------------
- # * 업로드
- #--------------------------------------------------------------------------
- def upload(filename, toname)
- filename.gsub!("/", "\\")
- path = sprintf("upload/%s/", @port)
- send('TYPE I')
- send(sprintf('MKD %s', path))
- send(sprintf('CWD %s', path))
- send(sprintf('STOR %s', filename))
- path.split("/").size.times do
- send('CDUP')
- end
- if toname.empty?
- folder = filename.split("\\")
- name = folder[folder.size - 1]
- for i in folder
- folder.pop if i.include?(".")
- end
- subpath = ""
- for i in folder
- subpath << i << "/"
- send(sprintf('MKD %s', subpath))
- end
- else
- if toname.include?("@@")
- toname.gsub!("@@", @host)
- end
- folder = toname.split("/")
- name = folder[folder.size - 1]
- unless name.include?(@host)
- for i in folder
- folder.pop if i.include?(".")
- end
- else
- file = filename.split("\\")
- name = file[file.size - 1]
- end
- subpath = ""
- for i in folder
- subpath << i << "/"
- send(sprintf('MKD %s', subpath))
- end
- end
- send(sprintf('RNFR %s', path + filename))
- send(sprintf('RNTO %s', subpath + name))
- send(sprintf('RMD %s', path))
- subpath + name
- end
- #--------------------------------------------------------------------------
- # * 이름 변경
- #--------------------------------------------------------------------------
- def rename(fromname, toname)
- send(sprintf('RNFR %s', fromname))
- send(sprintf('RNTO %s', toname))
- end
- #--------------------------------------------------------------------------
- # * 제거
- #--------------------------------------------------------------------------
- def delete(filename)
- send(sprintf('DELE %s', filename))
- end
- #--------------------------------------------------------------------------
- # * 폴더 변경
- #--------------------------------------------------------------------------
- def chdir(dirname)
- return send('CDUP') if dirname == ".."
- send(sprintf('CWD %s', dirname))
- end
- #--------------------------------------------------------------------------
- # * 폴더 생성
- #--------------------------------------------------------------------------
- def mkdir(dirname)
- send(sprintf('MKD %s', dirname))
- end
- #--------------------------------------------------------------------------
- # * 폴더 제거
- #--------------------------------------------------------------------------
- def rmdir(dirname)
- send(sprintf('RMD %s', dirname))
- end
- #--------------------------------------------------------------------------
- # * 닫기
- #--------------------------------------------------------------------------
- def close
- return if @sock.nil?
- CLOSESOCKET.call(@sock)
- @sock = nil
- end
- #--------------------------------------------------------------------------
- # * 준비
- #--------------------------------------------------------------------------
- def ready?
- return if @sock.nil?
- not select(0) == 0
- end
- #--------------------------------------------------------------------------
- # * 선택
- #--------------------------------------------------------------------------
- def select(timeout)
- ret = SELECT.call(1, [1, @sock].pack("ll"),
- 0, 0, [timeout, timeout * 1000000].pack("ll"))
- error if ret == -1
- ret
- end
- #--------------------------------------------------------------------------
- # * 수신
- #--------------------------------------------------------------------------
- def recv(len, flags=0)
- buf = "\0" * len
- len = RECV.call(@sock, buf, buf.size, flags)
- buf.gsub!("", "") if buf.include?("")
- error if len == -1
- buf
- end
- #--------------------------------------------------------------------------
- # * 발송
- #--------------------------------------------------------------------------
- def send(data, flags=0)
- return if @sock.nil?
- data = data.to_s + "\r\n"
- ret = SEND.call(@sock, data, data.size, flags)
- error if ret == -1
- ret
- end
- #--------------------------------------------------------------------------
- # * 소켓
- #--------------------------------------------------------------------------
- def socket(domain, type, protocol)
- SOCKET.call(domain, type, protocol)
- end
- #--------------------------------------------------------------------------
- # * 입출력 모드
- #--------------------------------------------------------------------------
- def ioctlsocket(cmd, value)
- buf = [value].pack("c")
- ret = IOCTLSOCKET.call(@sock, cmd, buf)
- error if ret == -1
- ret
- end
- #--------------------------------------------------------------------------
- # * 구조체
- #--------------------------------------------------------------------------
- def sockaddr_in(host, port)
- [2, port].pack("sn") + gethostbyname(host)[3] + [].pack("x8")
- rescue
- p $!
- nil
- end
- #--------------------------------------------------------------------------
- # * 호스트 이름
- #--------------------------------------------------------------------------
- def gethostbyname(name)
- data = GETHOSTBYNAME.call(name)
- host = data.ref(16).unpack('LLssL')
- name = host[0].ref(256).unpack("c*").pack("c*").split("\0")[0]
- list = host[4].ref(4).unpack('L')[0].ref(4).unpack("c*")
- list = list.pack("c*")
- [name, [], host[2], list]
- end
- #--------------------------------------------------------------------------
- # * 연결
- #--------------------------------------------------------------------------
- def connect(sockaddr)
- ret = CONNECT.call(@sock, sockaddr, sockaddr.size)
- error if ret == -1
- ret
- end
- #--------------------------------------------------------------------------
- # * 도착
- #--------------------------------------------------------------------------
- def gets
- buffer = ""
- while (line = recv(1)) != "\n"
- break if line == "\000"
- buffer << line
- end
- buffer
- end
- #--------------------------------------------------------------------------
- # * 패킷
- #--------------------------------------------------------------------------
- def packet(recv)
- case recv
- # Opening
- when %r(150 (.*))
- data = $1.split(" ")
- if data[0] == "Opening"
- if data[6].include?(".")
- unless data[7].nil?
- size = data[7]
- size.gsub!("(", "")
- size.gsub!(")", "")
- @size = size.to_i
- @file = @file.include?(".") ?
- @file : @file + data[6].to_s
- if @read != data[6].to_s
- # 다운로드
- Server.recv_file(@size, @file)
- else
- # 읽기
- handle(Server.recv_read(@size))
- end
- else
- if File.exist?(data[6].to_s)
- # 업로드
- Server.send_file(data[6].to_s)
- end
- end
- end
- end
- Server.close
- # QUIT
- when %r(221 (.*))
- Server.close
- close
- # Transfer complete
- when %r(226 (.*))
- Server.close
- close
- # PASV
- when %r(227 (.*))
- data = $1.split(" ")
- data = data[3].to_s
- data.gsub!("(", "")
- data.gsub!(")", "")
- data.gsub!(".", "")
- pasv = data.split(",")
- port = pasv[4].to_i
- port = 256 * port
- port += pasv[5].to_i
- host = pasv[0].to_s
- host << "." << pasv[1]
- host << "." << pasv[2]
- host << "." << pasv[3]
- Server.connect(host, port)
- @port = port.to_s
- # User Logged In
- when %r(230 (.*))
- send('STAT')
- send('PASV')
- # No such file
- when %r(550 (.*))
- Server.close
- close
- # Connected From
- when %r( Connected from (.*))
- data = $1.split(" ")
- @host = data[0].to_s
- end
- end
- #--------------------------------------------------------------------------
- # * 갱신
- #--------------------------------------------------------------------------
- def update
- packet(gets) if ready?
- end
- #--------------------------------------------------------------------------
- # * 에러 탐지
- #--------------------------------------------------------------------------
- def error_detect(errno)
- Errno.constants.detect { |c| Errno.const_get(c).new.errno == errno }
- end
- #--------------------------------------------------------------------------
- # * 에러
- #--------------------------------------------------------------------------
- def error
- errno = WSAGETLASTERROR.call
- errno = error_detect(errno).to_s
- case errno
- when 'EWOULDBLOCK'
- errno = nil
- end
- close if errno
- end
- #--------------------------------------------------------------------------
- # ** Server
- #--------------------------------------------------------------------------
- module Server
- #----------------------------------------------------------------------
- # * 인스턴스 변수
- #----------------------------------------------------------------------
- @sock = nil
- #----------------------------------------------------------------------
- # * 연결
- #----------------------------------------------------------------------
- def self.connect(host, port)
- return unless @sock.nil?
- @sock = socket(2, 1, 6)
- error if @sock == -1
- ioctlsocket(0x8004667e, 1)
- sockaddr = sockaddr_in(host, port)
- ret = CONNECT.call(@sock, sockaddr, sockaddr.size)
- error if ret == -1
- ret
- end
- #----------------------------------------------------------------------
- # * 닫기
- #----------------------------------------------------------------------
- def self.close
- return if @sock.nil?
- CLOSESOCKET.call(@sock)
- @sock = nil
- end
- #----------------------------------------------------------------------
- # * 수신
- #----------------------------------------------------------------------
- def self.recv(len, flags=0)
- buf = "\0" * len
- len = RECV.call(@sock, buf, buf.size, flags)
- buf.gsub!("", "") if buf.include?("")
- error if len == -1
- buf
- end
- #----------------------------------------------------------------------
- # * 발송
- #----------------------------------------------------------------------
- def self.send(data, flags=0)
- ret = SEND.call(@sock, data, data.size, flags)
- error if ret == -1
- ret
- end
- #----------------------------------------------------------------------
- # * 소켓
- #----------------------------------------------------------------------
- def self.socket(domain, type, protocol)
- SOCKET.call(domain, type, protocol)
- end
- #----------------------------------------------------------------------
- # * 입출력 모드
- #----------------------------------------------------------------------
- def self.ioctlsocket(cmd, value)
- buf = [value].pack("c")
- ret = IOCTLSOCKET.call(@sock, cmd, buf)
- error if ret == -1
- ret
- end
- #----------------------------------------------------------------------
- # * 구조체
- #----------------------------------------------------------------------
- def self.sockaddr_in(host, port)
- [2, port].pack("sn") + gethostbyname(host)[3] + [].pack("x8")
- rescue
- nil
- end
- #----------------------------------------------------------------------
- # * 호스트 이름
- #----------------------------------------------------------------------
- def self.gethostbyname(name)
- data = GETHOSTBYNAME.call(name)
- host = data.ref(16).unpack('LLssL')
- name = host[0].ref(256).unpack("c*").pack("c*").split("\0")[0]
- list = host[4].ref(4).unpack('L')[0].ref(4).unpack("c*")
- list = list.pack("c*")
- [name, [], host[2], list]
- end
- #----------------------------------------------------------------------
- # * 도착
- #----------------------------------------------------------------------
- def self.gets
- buffer = ""
- while (line = recv(1)) != "\n"
- break if line == "\000"
- buffer << line
- end
- buffer
- end
- #----------------------------------------------------------------------
- # * 파일 발송
- #----------------------------------------------------------------------
- def self.send_file(filename)
- read = ""
- File.open(filename, "rb") do |f|
- read = f.rewind
- read = f.readlines
- size = read.size
- size.times do |i|
- Graphics.update
- Input.update
- send(read[i])
- end
- end
- read
- end
- #----------------------------------------------------------------------
- # * 파일 수신
- #----------------------------------------------------------------------
- def self.recv_file(size, filename)
- data = ""
- gauge = 0
- speed = 1024
- size.times do |i|
- Graphics.update if i % speed / 2 == 0
- Input.update
- gauge += speed
- if gauge >= size
- gauge = gauge - speed
- speed = size - gauge
- data << recv(speed)
- break
- end
- data << recv(speed)
- end
- create_dir(filename)
- write_file(filename, data)
- data
- end
- #----------------------------------------------------------------------
- # * 파일 읽기
- #----------------------------------------------------------------------
- def self.recv_read(size)
- data = ""
- gauge = 0
- speed = 1024
- size.times do |i|
- Graphics.update
- Input.update
- gauge += speed
- if gauge >= size
- gauge = gauge - speed
- speed = size - gauge
- data << recv(speed)
- break
- end
- data << recv(speed)
- end
- data
- end
- #----------------------------------------------------------------------
- # * 폴더 생성
- #----------------------------------------------------------------------
- def self.create_dir(path)
- path = path.split("/")
- for i in path
- if i.include?(".")
- path.pop
- end
- end
- subpath = ""
- for i in path
- subpath << i << "/"
- Dir.mkdir(subpath) unless File.directory?(subpath)
- end
- subpath
- end
- #----------------------------------------------------------------------
- # * 폴더 생성
- #----------------------------------------------------------------------
- def self.write_file(filename, data)
- File.open(filename, "wb") do |f|
- f.write(data)
- end
- filename
- end
- #----------------------------------------------------------------------
- # * 에러 탐지
- #----------------------------------------------------------------------
- def self.error_detect(errno)
- Errno.constants.detect { |c| Errno.const_get(c).new.errno == errno }
- end
- #--------------------------------------------------------------------------
- # * 에러
- #--------------------------------------------------------------------------
- def self.error
- errno = WSAGETLASTERROR.call
- errno = error_detect(errno).to_s
- case errno
- when 'EWOULDBLOCK'
- errno = nil
- end
- close if errno
- end
- end
- end
- #==============================================================================
- # ** Win32API
- #==============================================================================
- class Win32API
- #--------------------------------------------------------------------------
- # * 동적 링크 라이브러리
- #--------------------------------------------------------------------------
- KERNEL = 'kernel32'
- #--------------------------------------------------------------------------
- # * kernel32
- #--------------------------------------------------------------------------
- RtlMoveMemory = new(KERNEL, 'RtlMoveMemory', 'ppl', 'l')
- end
- #==============================================================================
- # ** Win32
- #==============================================================================
- module Win32
- #--------------------------------------------------------------------------
- # * copymem
- #--------------------------------------------------------------------------
- def copymem(len)
- buf = "\0" * len
- Win32API::RtlMoveMemory.call(buf, self, len)
- buf
- end
- end
- #==============================================================================
- # ** Numeric
- #==============================================================================
- class Numeric
- #--------------------------------------------------------------------------
- # * 포함
- #--------------------------------------------------------------------------
- include(Win32)
- #--------------------------------------------------------------------------
- # * ref
- #--------------------------------------------------------------------------
- def ref(length)
- buffer = "\\" * length
- Win32API::RtlMoveMemory.call(buffer, self, length)
- buffer
- end
- end
- #==============================================================================
- # ** Graphics
- #==============================================================================
- module Graphics
- #--------------------------------------------------------------------------
- # * 셀프 클래스
- #--------------------------------------------------------------------------
- class << self
- #----------------------------------------------------------------------
- # * 메서드 별명
- #----------------------------------------------------------------------
- alias :up_date :update unless method_defined?(:up_date)
- #----------------------------------------------------------------------
- # * 갱신
- #----------------------------------------------------------------------
- def update
- up_date
- FTP.update
- end
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement