Advertisement
UNJONG

FTP

Sep 5th, 2016
135
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Ruby 24.22 KB | None | 0 0
  1. #==============================================================================
  2. # ** FTP
  3. #==============================================================================
  4.  
  5. class FTP
  6.  
  7.   #--------------------------------------------------------------------------
  8.   # * 서버
  9.   #--------------------------------------------------------------------------
  10.   HOST = '112.175.184.88'
  11.   PORT = 21
  12.  
  13.   #--------------------------------------------------------------------------
  14.   # * 정보
  15.   #--------------------------------------------------------------------------
  16.   USER = 'anonymous'
  17.   PASS = 'anonymous@'
  18.  
  19.   #--------------------------------------------------------------------------
  20.   # * 클래스 변수
  21.   #--------------------------------------------------------------------------
  22.   @@list = []
  23.  
  24.   #--------------------------------------------------------------------------
  25.   # * 셀프 클래스
  26.   #--------------------------------------------------------------------------
  27.   class << self
  28.    
  29.     #----------------------------------------------------------------------
  30.     # * 다운로드
  31.     #----------------------------------------------------------------------
  32.     def download(filename, path = "")
  33.       @@list.push([new, sprintf("download %s %s", filename, path)])
  34.     end
  35.    
  36.     #----------------------------------------------------------------------
  37.     # * 읽기
  38.     #----------------------------------------------------------------------
  39.     def read(filename)
  40.       @@list.push([new, sprintf("read %s", filename)])
  41.     end
  42.    
  43.     #----------------------------------------------------------------------
  44.     # * 업로드
  45.     #----------------------------------------------------------------------
  46.     def upload(filename, toname = "")
  47.       @@list.push([new, sprintf("upload %s %s", filename, toname)])
  48.     end
  49.    
  50.     #----------------------------------------------------------------------
  51.     # * 갱신
  52.     #----------------------------------------------------------------------
  53.     def update
  54.       unless @@list[0].nil?
  55.         unless @@list[0][0].sock
  56.           @@list.delete_at(0)
  57.           return
  58.         end
  59.         if @@list[0][0].port
  60.           case @@list[0][1]
  61.           when %r(download (.*) (.*))
  62.             @@list[0][0].download($1, $2)
  63.             @@list[0][1] = nil
  64.           when %r(read (.*))
  65.             @@list[0][0].read($1)
  66.             @@list[0][1] = nil
  67.           when %r(upload (.*) (.*))
  68.             @@list[0][0].upload($1, $2)
  69.             @@list[0][1] = nil
  70.           end
  71.         end
  72.         @@list[0][0].update
  73.       end
  74.     end
  75.    
  76.     #----------------------------------------------------------------------
  77.     # * 닫기
  78.     #----------------------------------------------------------------------
  79.     def close
  80.       @@list.each_index do |i|
  81.         @@list[i][0].close
  82.         @@list.delete_at(i)
  83.       end
  84.     end
  85.    
  86.     #----------------------------------------------------------------------
  87.     # * 사용중
  88.     #----------------------------------------------------------------------
  89.     def in_use?
  90.       @@list != []
  91.     end
  92.    
  93.     #----------------------------------------------------------------------
  94.     # * 데이터
  95.     #----------------------------------------------------------------------
  96.     def data
  97.       @@list[0][0] if in_use?
  98.     end
  99.   end
  100.  
  101.   #--------------------------------------------------------------------------
  102.   # * 동적 링크 라이브러리
  103.   #--------------------------------------------------------------------------
  104.   DLL = 'ws2_32'
  105.  
  106.   #--------------------------------------------------------------------------
  107.   # * Ws2_32
  108.   #--------------------------------------------------------------------------
  109.   IOCTLSOCKET     = Win32API.new(DLL, 'ioctlsocket',     'plp',    'l')
  110.   CLOSESOCKET     = Win32API.new(DLL, 'closesocket',     'p',      'l')
  111.   CONNECT         = Win32API.new(DLL, 'connect',         'ppl',    'l')
  112.   GETHOSTBYNAME   = Win32API.new(DLL, 'gethostbyname',   'p',      'l')
  113.   RECV            = Win32API.new(DLL, 'recv',            'ppll',   'l')
  114.   SELECT          = Win32API.new(DLL, 'select',          'lpppp',  'l')
  115.   SEND            = Win32API.new(DLL, 'send',            'ppll',   'l')
  116.   SOCKET          = Win32API.new(DLL, 'socket',          'lll',    'l')
  117.   WSAGETLASTERROR = Win32API.new(DLL, 'WSAGetLastError', '',       'l')
  118.  
  119.   #--------------------------------------------------------------------------
  120.   # * 공개 인스턴스 변수
  121.   #--------------------------------------------------------------------------
  122.   attr_reader :sock, :host, :port
  123.  
  124.   #--------------------------------------------------------------------------
  125.   # * 초기화
  126.   #--------------------------------------------------------------------------
  127.   def initialize
  128.     join
  129.   end
  130.  
  131.   #--------------------------------------------------------------------------
  132.   # * 접속
  133.   #--------------------------------------------------------------------------
  134.   def join
  135.     return unless @sock.nil?
  136.     @sock = socket(2, 1, 6)
  137.     error if @sock == -1
  138.     ioctlsocket(0x8004667e, 1)
  139.     sockaddr = sockaddr_in(HOST, PORT)
  140.     connect(sockaddr); sleep(0.1)
  141.     send(sprintf('USER %s', USER))
  142.     send(sprintf('PASS %s', PASS))
  143.   end
  144.  
  145.   #--------------------------------------------------------------------------
  146.   # * 다운로드
  147.   #--------------------------------------------------------------------------
  148.   def download(filename, path)
  149.     send('TYPE I')
  150.     @file = path
  151.     send(sprintf('RETR %s', filename))
  152.     filename
  153.   end
  154.  
  155.   #--------------------------------------------------------------------------
  156.   # * 읽기
  157.   #--------------------------------------------------------------------------
  158.   def read(filename)
  159.     send('TYPE I')
  160.     @read = filename
  161.     @file = filename
  162.     send(sprintf('RETR %s', filename))
  163.     filename
  164.   end
  165.  
  166.   #--------------------------------------------------------------------------
  167.   # * 업로드
  168.   #--------------------------------------------------------------------------
  169.   def upload(filename, toname)
  170.     filename.gsub!("/", "\\")
  171.     path = sprintf("upload/%s/", @port)
  172.     send('TYPE I')
  173.     send(sprintf('MKD %s', path))
  174.     send(sprintf('CWD %s', path))
  175.     send(sprintf('STOR %s', filename))
  176.     path.split("/").size.times do
  177.       send('CDUP')
  178.     end
  179.     if toname.empty?
  180.       folder = filename.split("\\")
  181.       name = folder[folder.size - 1]
  182.       for i in folder
  183.         folder.pop if i.include?(".")
  184.       end
  185.       subpath = ""
  186.       for i in folder
  187.         subpath << i << "/"
  188.         send(sprintf('MKD %s', subpath))
  189.       end
  190.     else
  191.       if toname.include?("@@")
  192.         toname.gsub!("@@", @host)
  193.       end
  194.       folder = toname.split("/")
  195.       name = folder[folder.size - 1]
  196.       unless name.include?(@host)
  197.         for i in folder
  198.           folder.pop if i.include?(".")
  199.         end
  200.       else
  201.         file = filename.split("\\")
  202.         name = file[file.size - 1]
  203.       end
  204.       subpath = ""
  205.       for i in folder
  206.         subpath << i << "/"
  207.         send(sprintf('MKD %s', subpath))
  208.       end
  209.     end
  210.     send(sprintf('RNFR %s', path + filename))
  211.     send(sprintf('RNTO %s', subpath + name))
  212.     send(sprintf('RMD %s', path))
  213.     subpath + name
  214.   end
  215.  
  216.   #--------------------------------------------------------------------------
  217.   # * 이름 변경
  218.   #--------------------------------------------------------------------------
  219.   def rename(fromname, toname)
  220.     send(sprintf('RNFR %s', fromname))
  221.     send(sprintf('RNTO %s', toname))
  222.   end
  223.  
  224.   #--------------------------------------------------------------------------
  225.   # * 제거
  226.   #--------------------------------------------------------------------------
  227.   def delete(filename)
  228.     send(sprintf('DELE %s', filename))
  229.   end
  230.  
  231.   #--------------------------------------------------------------------------
  232.   # * 폴더 변경
  233.   #--------------------------------------------------------------------------
  234.   def chdir(dirname)
  235.     return send('CDUP') if dirname == ".."
  236.     send(sprintf('CWD %s', dirname))
  237.   end
  238.  
  239.   #--------------------------------------------------------------------------
  240.   # * 폴더 생성
  241.   #--------------------------------------------------------------------------
  242.   def mkdir(dirname)
  243.     send(sprintf('MKD %s', dirname))
  244.   end
  245.  
  246.   #--------------------------------------------------------------------------
  247.   # * 폴더 제거
  248.   #--------------------------------------------------------------------------
  249.   def rmdir(dirname)
  250.     send(sprintf('RMD %s', dirname))
  251.   end
  252.  
  253.   #--------------------------------------------------------------------------
  254.   # * 닫기
  255.   #--------------------------------------------------------------------------
  256.   def close
  257.     return if @sock.nil?
  258.     CLOSESOCKET.call(@sock)
  259.     @sock   = nil
  260.   end
  261.  
  262.   #--------------------------------------------------------------------------
  263.   # * 준비
  264.   #--------------------------------------------------------------------------
  265.   def ready?
  266.     return if @sock.nil?
  267.     not select(0) == 0
  268.   end
  269.  
  270.   #--------------------------------------------------------------------------
  271.   # * 선택
  272.   #--------------------------------------------------------------------------
  273.   def select(timeout)
  274.     ret = SELECT.call(1, [1, @sock].pack("ll"),
  275.     0, 0, [timeout, timeout * 1000000].pack("ll"))
  276.     error if ret == -1
  277.     ret
  278.   end
  279.  
  280.   #--------------------------------------------------------------------------
  281.   # * 수신
  282.   #--------------------------------------------------------------------------
  283.   def recv(len, flags=0)
  284.     buf = "\0" * len
  285.     len = RECV.call(@sock, buf, buf.size, flags)
  286.     buf.gsub!("", "") if buf.include?("")
  287.     error if len == -1
  288.     buf
  289.   end
  290.  
  291.   #--------------------------------------------------------------------------
  292.   # * 발송
  293.   #--------------------------------------------------------------------------
  294.   def send(data, flags=0)
  295.     return if @sock.nil?
  296.     data = data.to_s + "\r\n"
  297.     ret = SEND.call(@sock, data, data.size, flags)
  298.     error if ret == -1
  299.     ret
  300.   end
  301.  
  302.   #--------------------------------------------------------------------------
  303.   # * 소켓
  304.   #--------------------------------------------------------------------------
  305.   def socket(domain, type, protocol)
  306.     SOCKET.call(domain, type, protocol)
  307.   end
  308.  
  309.   #--------------------------------------------------------------------------
  310.   # * 입출력 모드
  311.   #--------------------------------------------------------------------------
  312.   def ioctlsocket(cmd, value)
  313.     buf = [value].pack("c")
  314.     ret = IOCTLSOCKET.call(@sock, cmd, buf)
  315.     error if ret == -1
  316.     ret
  317.   end
  318.  
  319.   #--------------------------------------------------------------------------
  320.   # * 구조체
  321.   #--------------------------------------------------------------------------
  322.   def sockaddr_in(host, port)
  323.     [2, port].pack("sn") + gethostbyname(host)[3] + [].pack("x8")
  324.   rescue
  325.     p $!
  326.     nil
  327.   end
  328.  
  329.   #--------------------------------------------------------------------------
  330.   # * 호스트 이름
  331.   #--------------------------------------------------------------------------
  332.   def gethostbyname(name)
  333.     data = GETHOSTBYNAME.call(name)
  334.     host = data.ref(16).unpack('LLssL')
  335.     name = host[0].ref(256).unpack("c*").pack("c*").split("\0")[0]
  336.     list = host[4].ref(4).unpack('L')[0].ref(4).unpack("c*")
  337.     list = list.pack("c*")
  338.     [name, [], host[2], list]
  339.   end
  340.  
  341.   #--------------------------------------------------------------------------
  342.   # * 연결
  343.   #--------------------------------------------------------------------------
  344.   def connect(sockaddr)
  345.     ret = CONNECT.call(@sock, sockaddr, sockaddr.size)
  346.     error if ret == -1
  347.     ret
  348.   end
  349.  
  350.   #--------------------------------------------------------------------------
  351.   # * 도착
  352.   #--------------------------------------------------------------------------
  353.   def gets
  354.     buffer = ""
  355.     while (line = recv(1)) != "\n"
  356.       break if line == "\000"
  357.       buffer << line
  358.     end
  359.     buffer
  360.   end
  361.  
  362.   #--------------------------------------------------------------------------
  363.   # * 패킷
  364.   #--------------------------------------------------------------------------
  365.   def packet(recv)
  366.     case recv
  367.     # Opening
  368.     when %r(150 (.*))
  369.       data = $1.split(" ")
  370.       if data[0] == "Opening"
  371.         if data[6].include?(".")
  372.           unless data[7].nil?
  373.             size = data[7]
  374.             size.gsub!("(", "")
  375.             size.gsub!(")", "")
  376.             @size = size.to_i
  377.             @file = @file.include?(".") ?
  378.             @file : @file + data[6].to_s
  379.             if @read != data[6].to_s
  380.               # 다운로드
  381.               Server.recv_file(@size, @file)
  382.             else
  383.               # 읽기
  384.               handle(Server.recv_read(@size))
  385.             end
  386.           else
  387.             if File.exist?(data[6].to_s)
  388.               # 업로드
  389.               Server.send_file(data[6].to_s)
  390.             end
  391.           end
  392.         end
  393.       end
  394.       Server.close
  395.     # QUIT
  396.     when %r(221 (.*))
  397.       Server.close
  398.       close
  399.     # Transfer complete
  400.     when %r(226 (.*))
  401.       Server.close
  402.       close
  403.     # PASV
  404.     when %r(227 (.*))
  405.       data = $1.split(" ")
  406.       data = data[3].to_s
  407.       data.gsub!("(", "")
  408.       data.gsub!(")", "")
  409.       data.gsub!(".", "")
  410.       pasv = data.split(",")
  411.       port = pasv[4].to_i
  412.       port = 256 * port
  413.       port += pasv[5].to_i
  414.       host = pasv[0].to_s
  415.       host << "." << pasv[1]
  416.       host << "." << pasv[2]
  417.       host << "." << pasv[3]
  418.       Server.connect(host, port)
  419.       @port = port.to_s
  420.     # User Logged In
  421.     when %r(230 (.*))
  422.       send('STAT')
  423.       send('PASV')
  424.     # No such file
  425.     when %r(550 (.*))
  426.       Server.close
  427.       close
  428.     # Connected From
  429.     when %r( Connected from (.*))
  430.       data  = $1.split(" ")
  431.       @host = data[0].to_s
  432.     end
  433.   end
  434.  
  435.   #--------------------------------------------------------------------------
  436.   # * 갱신
  437.   #--------------------------------------------------------------------------
  438.   def update
  439.     packet(gets) if ready?
  440.   end
  441.  
  442.   #--------------------------------------------------------------------------
  443.   # * 에러 탐지
  444.   #--------------------------------------------------------------------------
  445.   def error_detect(errno)
  446.     Errno.constants.detect { |c| Errno.const_get(c).new.errno == errno }
  447.   end
  448.  
  449.   #--------------------------------------------------------------------------
  450.   # * 에러
  451.   #--------------------------------------------------------------------------
  452.   def error
  453.     errno = WSAGETLASTERROR.call
  454.     errno = error_detect(errno).to_s
  455.     case errno
  456.     when 'EWOULDBLOCK'
  457.       errno = nil
  458.     end
  459.     close if errno
  460.   end
  461.  
  462.   #--------------------------------------------------------------------------
  463.   # ** Server
  464.   #--------------------------------------------------------------------------
  465.   module Server
  466.    
  467.     #----------------------------------------------------------------------
  468.     # * 인스턴스 변수
  469.     #----------------------------------------------------------------------
  470.     @sock = nil
  471.    
  472.     #----------------------------------------------------------------------
  473.     # * 연결
  474.     #----------------------------------------------------------------------
  475.     def self.connect(host, port)
  476.       return unless @sock.nil?
  477.       @sock = socket(2, 1, 6)
  478.       error if @sock == -1
  479.       ioctlsocket(0x8004667e, 1)
  480.       sockaddr = sockaddr_in(host, port)
  481.       ret = CONNECT.call(@sock, sockaddr, sockaddr.size)
  482.       error if ret == -1
  483.       ret
  484.     end
  485.    
  486.     #----------------------------------------------------------------------
  487.     # * 닫기
  488.     #----------------------------------------------------------------------
  489.     def self.close
  490.       return if @sock.nil?
  491.       CLOSESOCKET.call(@sock)
  492.       @sock = nil
  493.     end
  494.    
  495.     #----------------------------------------------------------------------
  496.     # * 수신
  497.     #----------------------------------------------------------------------
  498.     def self.recv(len, flags=0)
  499.       buf = "\0" * len
  500.       len = RECV.call(@sock, buf, buf.size, flags)
  501.       buf.gsub!("", "") if buf.include?("")
  502.       error if len == -1
  503.       buf
  504.     end
  505.    
  506.     #----------------------------------------------------------------------
  507.     # * 발송
  508.     #----------------------------------------------------------------------
  509.     def self.send(data, flags=0)
  510.       ret = SEND.call(@sock, data, data.size, flags)
  511.       error if ret == -1
  512.       ret
  513.     end
  514.    
  515.     #----------------------------------------------------------------------
  516.     # * 소켓
  517.     #----------------------------------------------------------------------
  518.     def self.socket(domain, type, protocol)
  519.       SOCKET.call(domain, type, protocol)
  520.     end
  521.    
  522.     #----------------------------------------------------------------------
  523.     # * 입출력 모드
  524.     #----------------------------------------------------------------------
  525.     def self.ioctlsocket(cmd, value)
  526.       buf = [value].pack("c")
  527.       ret = IOCTLSOCKET.call(@sock, cmd, buf)
  528.       error if ret == -1
  529.       ret
  530.     end
  531.    
  532.     #----------------------------------------------------------------------
  533.     # * 구조체
  534.     #----------------------------------------------------------------------
  535.     def self.sockaddr_in(host, port)
  536.       [2, port].pack("sn") + gethostbyname(host)[3] + [].pack("x8")
  537.     rescue
  538.       nil
  539.     end
  540.    
  541.     #----------------------------------------------------------------------
  542.     # * 호스트 이름
  543.     #----------------------------------------------------------------------
  544.     def self.gethostbyname(name)
  545.       data = GETHOSTBYNAME.call(name)
  546.       host = data.ref(16).unpack('LLssL')
  547.       name = host[0].ref(256).unpack("c*").pack("c*").split("\0")[0]
  548.       list = host[4].ref(4).unpack('L')[0].ref(4).unpack("c*")
  549.       list = list.pack("c*")
  550.       [name, [], host[2], list]
  551.     end
  552.    
  553.     #----------------------------------------------------------------------
  554.     # * 도착
  555.     #----------------------------------------------------------------------
  556.     def self.gets
  557.       buffer = ""
  558.       while (line = recv(1)) != "\n"
  559.         break if line == "\000"
  560.         buffer << line
  561.       end
  562.       buffer
  563.     end
  564.    
  565.     #----------------------------------------------------------------------
  566.     # * 파일 발송
  567.     #----------------------------------------------------------------------
  568.     def self.send_file(filename)
  569.       read  = ""
  570.       File.open(filename, "rb") do |f|
  571.         read = f.rewind
  572.         read = f.readlines
  573.         size = read.size
  574.         size.times do |i|
  575.           Graphics.update
  576.           Input.update
  577.           send(read[i])
  578.         end
  579.       end
  580.       read
  581.     end
  582.    
  583.     #----------------------------------------------------------------------
  584.     # * 파일 수신
  585.     #----------------------------------------------------------------------
  586.     def self.recv_file(size, filename)
  587.       data  = ""
  588.       gauge = 0
  589.       speed = 1024
  590.       size.times do |i|
  591.         Graphics.update if i % speed / 2 == 0
  592.         Input.update
  593.         gauge += speed
  594.         if gauge >= size
  595.           gauge = gauge - speed
  596.           speed = size  - gauge
  597.           data << recv(speed)
  598.           break
  599.         end
  600.         data << recv(speed)
  601.       end
  602.       create_dir(filename)
  603.       write_file(filename, data)
  604.       data
  605.     end
  606.    
  607.     #----------------------------------------------------------------------
  608.     # * 파일 읽기
  609.     #----------------------------------------------------------------------
  610.     def self.recv_read(size)
  611.       data  = ""
  612.       gauge = 0
  613.       speed = 1024
  614.       size.times do |i|
  615.         Graphics.update
  616.         Input.update
  617.         gauge += speed
  618.         if gauge >= size
  619.           gauge = gauge - speed
  620.           speed = size  - gauge
  621.           data << recv(speed)
  622.           break
  623.         end
  624.         data << recv(speed)
  625.       end
  626.       data
  627.     end
  628.    
  629.     #----------------------------------------------------------------------
  630.     # * 폴더 생성
  631.     #----------------------------------------------------------------------
  632.     def self.create_dir(path)
  633.       path = path.split("/")
  634.       for i in path
  635.         if i.include?(".")
  636.           path.pop
  637.         end
  638.       end
  639.       subpath = ""
  640.       for i in path
  641.         subpath << i << "/"
  642.         Dir.mkdir(subpath) unless File.directory?(subpath)
  643.       end
  644.       subpath
  645.     end
  646.    
  647.     #----------------------------------------------------------------------
  648.     # * 폴더 생성
  649.     #----------------------------------------------------------------------
  650.     def self.write_file(filename, data)
  651.       File.open(filename, "wb") do |f|
  652.         f.write(data)
  653.       end
  654.       filename
  655.     end
  656.    
  657.     #----------------------------------------------------------------------
  658.     # * 에러 탐지
  659.     #----------------------------------------------------------------------
  660.     def self.error_detect(errno)
  661.       Errno.constants.detect { |c| Errno.const_get(c).new.errno == errno }
  662.     end
  663.    
  664.     #--------------------------------------------------------------------------
  665.     # * 에러
  666.     #--------------------------------------------------------------------------
  667.     def self.error
  668.       errno = WSAGETLASTERROR.call
  669.       errno = error_detect(errno).to_s
  670.       case errno
  671.       when 'EWOULDBLOCK'
  672.         errno = nil
  673.       end
  674.       close if errno
  675.     end
  676.   end
  677. end
  678.  
  679. #==============================================================================
  680. # ** Win32API
  681. #==============================================================================
  682.  
  683. class Win32API
  684.  
  685.   #--------------------------------------------------------------------------
  686.   # * 동적 링크 라이브러리
  687.   #--------------------------------------------------------------------------
  688.   KERNEL = 'kernel32'
  689.  
  690.   #--------------------------------------------------------------------------
  691.   # * kernel32
  692.   #--------------------------------------------------------------------------
  693.   RtlMoveMemory = new(KERNEL, 'RtlMoveMemory', 'ppl', 'l')
  694. end
  695.  
  696. #==============================================================================
  697. # ** Win32
  698. #==============================================================================
  699.  
  700. module Win32
  701.  
  702.   #--------------------------------------------------------------------------
  703.   # * copymem
  704.   #--------------------------------------------------------------------------
  705.   def copymem(len)
  706.     buf = "\0" * len
  707.     Win32API::RtlMoveMemory.call(buf, self, len)
  708.     buf
  709.   end
  710. end
  711.  
  712. #==============================================================================
  713. # ** Numeric
  714. #==============================================================================
  715.  
  716. class Numeric
  717.  
  718.   #--------------------------------------------------------------------------
  719.   # * 포함
  720.   #--------------------------------------------------------------------------
  721.   include(Win32)
  722.  
  723.   #--------------------------------------------------------------------------
  724.   # * ref
  725.   #--------------------------------------------------------------------------
  726.   def ref(length)
  727.     buffer = "\\" * length
  728.     Win32API::RtlMoveMemory.call(buffer, self, length)
  729.     buffer
  730.   end
  731. end
  732.  
  733. #==============================================================================
  734. # ** Graphics
  735. #==============================================================================
  736.  
  737. module Graphics
  738.  
  739.   #--------------------------------------------------------------------------
  740.   # * 셀프 클래스
  741.   #--------------------------------------------------------------------------
  742.   class << self
  743.    
  744.     #----------------------------------------------------------------------
  745.     # * 메서드 별명
  746.     #----------------------------------------------------------------------
  747.     alias :up_date :update unless method_defined?(:up_date)
  748.    
  749.     #----------------------------------------------------------------------
  750.     # * 갱신
  751.     #----------------------------------------------------------------------
  752.     def update
  753.       up_date
  754.       FTP.update
  755.     end
  756.   end
  757. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement