From d0004fd49de84b860cde2721a74a50f3db1fe3b5 Mon Sep 17 00:00:00 2001 From: Louis Marti Date: Wed, 17 Feb 2016 11:32:21 -0500 Subject: [PATCH] GET + File Upload Restructured files. Fixed GET method. Added File Upload. --- interface/{wgo.player-2.0 => server}/go.html | 3 + interface/server/goServer.py | 466 ++++++++++-------- .../wgo/basicplayer.commentbox.js | 0 .../wgo/basicplayer.component.js | 0 .../wgo/basicplayer.control.js | 0 .../wgo/basicplayer.infobox.js | 0 .../wgo/basicplayer.js | 0 .../{wgo.player-2.0 => server}/wgo/kifu.js | 0 .../wgo/player.editable.js | 0 .../{wgo.player-2.0 => server}/wgo/player.js | 0 .../wgo/player.permalink.js | 0 .../wgo/scoremode.js | 0 .../wgo/sgfparser.js | 0 .../{wgo.player-2.0 => server}/wgo/wgo.js | 0 .../{wgo.player-2.0 => server}/wgo/wgo.min.js | 0 .../wgo/wgo.player.css | 0 .../wgo/wgo.player.min.js | 0 .../{wgo.player-2.0 => server}/wgo/wood1.jpg | Bin interface/wgo.player-2.0/UI.html | 26 - 19 files changed, 270 insertions(+), 225 deletions(-) rename interface/{wgo.player-2.0 => server}/go.html (87%) rename interface/{wgo.player-2.0 => server}/wgo/basicplayer.commentbox.js (100%) rename interface/{wgo.player-2.0 => server}/wgo/basicplayer.component.js (100%) rename interface/{wgo.player-2.0 => server}/wgo/basicplayer.control.js (100%) rename interface/{wgo.player-2.0 => server}/wgo/basicplayer.infobox.js (100%) rename interface/{wgo.player-2.0 => server}/wgo/basicplayer.js (100%) rename interface/{wgo.player-2.0 => server}/wgo/kifu.js (100%) rename interface/{wgo.player-2.0 => server}/wgo/player.editable.js (100%) rename interface/{wgo.player-2.0 => server}/wgo/player.js (100%) rename interface/{wgo.player-2.0 => server}/wgo/player.permalink.js (100%) rename interface/{wgo.player-2.0 => server}/wgo/scoremode.js (100%) rename interface/{wgo.player-2.0 => server}/wgo/sgfparser.js (100%) rename interface/{wgo.player-2.0 => server}/wgo/wgo.js (100%) rename interface/{wgo.player-2.0 => server}/wgo/wgo.min.js (100%) rename interface/{wgo.player-2.0 => server}/wgo/wgo.player.css (100%) rename interface/{wgo.player-2.0 => server}/wgo/wgo.player.min.js (100%) rename interface/{wgo.player-2.0 => server}/wgo/wood1.jpg (100%) delete mode 100644 interface/wgo.player-2.0/UI.html diff --git a/interface/wgo.player-2.0/go.html b/interface/server/go.html similarity index 87% rename from interface/wgo.player-2.0/go.html rename to interface/server/go.html index 1f3fc92d5..109a7d9e5 100644 --- a/interface/wgo.player-2.0/go.html +++ b/interface/server/go.html @@ -6,6 +6,9 @@ +
+ +
Sorry, your browser doesn't support WGo.js. Download SGF directly.
diff --git a/interface/server/goServer.py b/interface/server/goServer.py index f11e0f81d..5be882015 100644 --- a/interface/server/goServer.py +++ b/interface/server/goServer.py @@ -1,212 +1,280 @@ +__all__ = ["SimpleHTTPRequestHandler"] + +import os +import posixpath import BaseHTTPServer +import urllib import cgi -import logging -import os -import time +import shutil +import mimetypes +import re +try: + from cStringIO import StringIO +except ImportError: + from StringIO import StringIO -HOST_NAME = 'localhost' -PORT_NUMBER = 9000 +class SimpleHTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): -class MyHandler(BaseHTTPServer.BaseHTTPRequestHandler): - def do_HEAD(s): - s.send_response(200) - s.send_header("Content-type", "text/html") - s.end_headers() + """Simple HTTP request handler with GET/HEAD/POST commands. - def do_GET(self): - self.path = "..\wgo.player-2.0\go.html" + This serves files from the current directory and any of its + subdirectories. The MIME type for files is determined by + calling the .guess_type() method. And can reveive file uploaded + by client. - logging.debug('GET %s' % (self.path)) + The GET/HEAD/POST requests are identical except that the HEAD + request omits the actual contents of the file. - # Parse out the arguments. - # The arguments follow a '?' in the URL. Here is an example: - # http://example.com?arg1=val1 - args = {} - idx = self.path.find('?') + """ - if idx >= 0: - rpath = self.path[:idx] - args = cgi.parse_qs(self.path[idx+1:]) - else: - rpath = self.path - - # Print out logging information about the path and args. - if 'content-type' in self.headers: - ctype, _ = cgi.parse_header(self.headers['content-type']) - logging.debug('TYPE %s' % (ctype)) - - logging.debug('PATH %s' % (rpath)) - logging.debug('ARGS %d' % (len(args))) - - if len(args): - i = 0 - for key in sorted(args): - logging.debug('ARG[%d] %s=%s' % (i, key, args[key])) - i += 1 - - # Check to see whether the file is stored locally, - # if it is, display it. - # There is special handling for http://127.0.0.1/info. That URL - # displays some internal information. - if self.path == '/info' or self.path == '/info/': - self.send_response(200) # OK - self.send_header('Content-type', 'text/html') - self.end_headers() - self.info() + server_version = "SimpleHTTPWithUpload/" + + def do_GET(self): + """Serve a GET request.""" + f = self.send_head() + if f: + self.copyfile(f, self.wfile) + f.close() + + def do_HEAD(self): + """Serve a HEAD request.""" + f = self.send_head() + if f: + f.close() + + def do_POST(self): + """Serve a POST request.""" + r, info = self.deal_post_data() + print r, info, "by: ", self.client_address + f = StringIO() + f.write('') + f.write("\nUpload Result Page\n") + f.write("\n

Upload Result Page

\n") + f.write("
\n") + if r: + f.write("Success:") else: - # Get the file path. - path = rpath - dirpath = None - logging.debug('FILE %s' % (path)) - - # If it is a directory look for index.html - # or process it directly if there are 3 - # trailing slashed. - if rpath[-3:] == '///': - dirpath = path - elif os.path.exists(path) and os.path.isdir(path): - dirpath = path # the directory portion - index_files = ['/index.html', '/index.htm', ] - for index_file in index_files: - tmppath = path + index_file - if os.path.exists(tmppath): - path = tmppath - break - - # Allow the user to type "///" at the end to see the - # directory listing. - if os.path.exists(path) and os.path.isfile(path): - # This is valid file, send it as the response - # after determining whether it is a type that - # the server recognizes. - _, ext = os.path.splitext(path) - ext = ext.lower() - content_type = { - '.css': 'text/css', - '.gif': 'image/gif', - '.htm': 'text/html', - '.html': 'text/html', - '.jpeg': 'image/jpeg', - '.jpg': 'image/jpg', - '.js': 'text/javascript', - '.png': 'image/png', - '.text': 'text/plain', - '.txt': 'text/plain', - } - - # If it is a known extension, set the correct - # content type in the response. - if ext in content_type: - self.send_response(200) # OK - self.send_header('Content-type', content_type[ext]) - self.end_headers() - - with open(path) as ifp: - self.wfile.write(ifp.read()) - else: - # Unknown file type or a directory. - # Treat it as plain text. - self.send_response(200) # OK - self.send_header('Content-type', 'text/plain') - self.end_headers() - - with open(path) as ifp: - self.wfile.write(ifp.read()) + f.write("Failed:") + f.write(info) + f.write("
back" % self.headers['referer']) + f.write("
Powerd By: bones7456, check new version at ") + f.write("") + f.write("here.\n\n") + length = f.tell() + f.seek(0) + self.send_response(200) + self.send_header("Content-type", "text/html") + self.send_header("Content-Length", str(length)) + self.end_headers() + if f: + self.copyfile(f, self.wfile) + f.close() + + def deal_post_data(self): + boundary = self.headers.plisttext.split("=")[1] + remainbytes = int(self.headers['content-length']) + line = self.rfile.readline() + remainbytes -= len(line) + if not boundary in line: + return (False, "Content NOT begin with boundary") + line = self.rfile.readline() + remainbytes -= len(line) + fn = re.findall(r'Content-Disposition.*name="file"; filename="(.*)"', line) + if not fn: + return (False, "Can't find out file name...") + path = self.translate_path(self.path) + fn = os.path.join(path, fn[0]) + line = self.rfile.readline() + remainbytes -= len(line) + line = self.rfile.readline() + remainbytes -= len(line) + try: + out = open(fn, 'wb') + except IOError: + return (False, "Can't create file to write, do you have permission to write?") + + preline = self.rfile.readline() + remainbytes -= len(preline) + while remainbytes > 0: + line = self.rfile.readline() + remainbytes -= len(line) + if boundary in line: + preline = preline[0:-1] + if preline.endswith('\r'): + preline = preline[0:-1] + out.write(preline) + out.close() + return (True, "File '%s' upload success!" % fn) else: - if dirpath is None: - # Invalid file path, respond with a server access error - self.send_response(500) # generic server error for now - self.send_header('Content-type', 'text/html') - self.end_headers() - - self.wfile.write('') - self.wfile.write(' ') - self.wfile.write(' Server Access Error') - self.wfile.write(' ') - self.wfile.write(' ') - self.wfile.write('

Server access error.

') - self.wfile.write('

%r

' % (repr(self.path))) - self.wfile.write('

Back

' % (rpath)) - self.wfile.write(' ') - self.wfile.write('') - else: - # List the directory contents. Allow simple navigation. - logging.debug('DIR %s' % (dirpath)) - - self.send_response(200) # OK - self.send_header('Content-type', 'text/html') - self.end_headers() - - self.wfile.write('') - self.wfile.write(' ') - self.wfile.write(' %s' % (dirpath)) - self.wfile.write(' ') - self.wfile.write(' ') - self.wfile.write(' Home
' % ('/')); - - # Make the directory path navigable. - dirstr = '' - href = None - for seg in rpath.split('/'): - if href is None: - href = seg - else: - href = href + '/' + seg - dirstr += '/' - dirstr += '%s' % (href, seg) - self.wfile.write('

Directory: %s

' % (dirstr)) - - # Write out the simple directory list (name and size). - self.wfile.write(' ') - self.wfile.write(' ') - fnames = ['..'] - fnames.extend(sorted(os.listdir(dirpath), key=str.lower)) - for fname in fnames: - self.wfile.write(' ') - self.wfile.write(' ') - self.wfile.write(' ') - self.wfile.write(' ' % (os.path.getsize(fpath))) - self.wfile.write(' ') - self.wfile.write(' ') - self.wfile.write('
') - path = rpath + '/' + fname - fpath = os.path.join(dirpath, fname) - if os.path.isdir(path): - self.wfile.write(' %s/' % (path, fname)) - else: - self.wfile.write(' %s' % (path, fname)) - self.wfile.write(' %d
') - self.wfile.write(' ') - self.wfile.write('') - - - - # def do_GET(s): - # s.send_response(200) - # s.send_header("Content-type", "text/html") - # s.end_headers() - # - # f = open("..\wgo.player-2.0\go.html") - # - # s.wfile.write(f.read()) - # f.close() - # - # if url[0] == "..\wgo.player-2.0\wgo\wgo.min.js": - # f = open("..\wgo.player-2.0\wgo\wgo.min.js", "rb") - # - # for each_line in f: - # s.wfile.write(each_line) - # return + out.write(preline) + preline = line + return (False, "Unexpect Ends of data.") -if __name__ == '__main__': - server_class = BaseHTTPServer.HTTPServer - httpd = server_class((HOST_NAME, PORT_NUMBER), MyHandler) - print time.asctime(), "Server Starts - %s:%s" % (HOST_NAME, PORT_NUMBER) + def send_head(self): + """Common code for GET and HEAD commands. + + This sends the response code and MIME headers. + + Return value is either a file object (which has to be copied + to the outputfile by the caller unless the command was HEAD, + and must be closed by the caller under all circumstances), or + None, in which case the caller has nothing further to do. + + """ + path = self.translate_path(self.path) + f = None + if os.path.isdir(path): + if not self.path.endswith('/'): + # redirect browser - doing basically what apache does + self.send_response(301) + self.send_header("Location", self.path + "/") + self.end_headers() + return None + for index in "index.html", "index.htm": + index = os.path.join(path, index) + if os.path.exists(index): + path = index + break + else: + return self.list_directory(path) + ctype = self.guess_type(path) + try: + # Always read in binary mode. Opening files in text mode may cause + # newline translations, making the actual size of the content + # transmitted *less* than the content-length! + f = open(path, 'rb') + except IOError: + self.send_error(404, "File not found") + return None + self.send_response(200) + self.send_header("Content-type", ctype) + fs = os.fstat(f.fileno()) + self.send_header("Content-Length", str(fs[6])) + self.send_header("Last-Modified", self.date_time_string(fs.st_mtime)) + self.end_headers() + return f + + def list_directory(self, path): + """Helper to produce a directory listing (absent index.html). + + Return value is either a file object, or None (indicating an + error). In either case, the headers are sent, making the + interface the same as for send_head(). - try: - httpd.serve_forever() - except KeyboardInterrupt: - pass - httpd.server_close() + """ + try: + list = os.listdir(path) + except os.error: + self.send_error(404, "No permission to list directory") + return None + list.sort(key=lambda a: a.lower()) + f = StringIO() + displaypath = cgi.escape(urllib.unquote(self.path)) + f.write('') + f.write("\nDirectory listing for %s\n" % displaypath) + f.write("\n

Directory listing for %s

\n" % displaypath) + f.write("
\n") + f.write("
") + f.write("") + f.write("
\n") + f.write("
\n\n
\n\n\n") + length = f.tell() + f.seek(0) + self.send_response(200) + self.send_header("Content-type", "text/html") + self.send_header("Content-Length", str(length)) + self.end_headers() + return f - print time.asctime(), "Server Stops - %s:%s" % (HOST_NAME, PORT_NUMBER) \ No newline at end of file + def translate_path(self, path): + """Translate a /-separated PATH to the local filename syntax. + + Components that mean special things to the local file system + (e.g. drive or directory names) are ignored. (XXX They should + probably be diagnosed.) + + """ + # abandon query parameters + path = path.split('?',1)[0] + path = path.split('#',1)[0] + path = posixpath.normpath(urllib.unquote(path)) + words = path.split('/') + words = filter(None, words) + path = os.getcwd() + for word in words: + drive, word = os.path.splitdrive(word) + head, word = os.path.split(word) + if word in (os.curdir, os.pardir): continue + path = os.path.join(path, word) + return path + + def copyfile(self, source, outputfile): + """Copy all data between two file objects. + + The SOURCE argument is a file object open for reading + (or anything with a read() method) and the DESTINATION + argument is a file object open for writing (or + anything with a write() method). + + The only reason for overriding this would be to change + the block size or perhaps to replace newlines by CRLF + -- note however that this the default server uses this + to copy binary data as well. + + """ + shutil.copyfileobj(source, outputfile) + + def guess_type(self, path): + """Guess the type of a file. + + Argument is a PATH (a filename). + + Return value is a string of the form type/subtype, + usable for a MIME Content-type header. + + The default implementation looks the file's extension + up in the table self.extensions_map, using application/octet-stream + as a default; however it would be permissible (if + slow) to look inside the data to make a better guess. + + """ + + base, ext = posixpath.splitext(path) + if ext in self.extensions_map: + return self.extensions_map[ext] + ext = ext.lower() + if ext in self.extensions_map: + return self.extensions_map[ext] + else: + return self.extensions_map[''] + + if not mimetypes.inited: + mimetypes.init() # try to read system mime.types + extensions_map = mimetypes.types_map.copy() + extensions_map.update({ + '': 'application/octet-stream', # Default + '.py': 'text/plain', + '.c': 'text/plain', + '.h': 'text/plain', + }) + + +def test(HandlerClass = SimpleHTTPRequestHandler, + ServerClass = BaseHTTPServer.HTTPServer): + BaseHTTPServer.test(HandlerClass, ServerClass) + +if __name__ == '__main__': + test() \ No newline at end of file diff --git a/interface/wgo.player-2.0/wgo/basicplayer.commentbox.js b/interface/server/wgo/basicplayer.commentbox.js similarity index 100% rename from interface/wgo.player-2.0/wgo/basicplayer.commentbox.js rename to interface/server/wgo/basicplayer.commentbox.js diff --git a/interface/wgo.player-2.0/wgo/basicplayer.component.js b/interface/server/wgo/basicplayer.component.js similarity index 100% rename from interface/wgo.player-2.0/wgo/basicplayer.component.js rename to interface/server/wgo/basicplayer.component.js diff --git a/interface/wgo.player-2.0/wgo/basicplayer.control.js b/interface/server/wgo/basicplayer.control.js similarity index 100% rename from interface/wgo.player-2.0/wgo/basicplayer.control.js rename to interface/server/wgo/basicplayer.control.js diff --git a/interface/wgo.player-2.0/wgo/basicplayer.infobox.js b/interface/server/wgo/basicplayer.infobox.js similarity index 100% rename from interface/wgo.player-2.0/wgo/basicplayer.infobox.js rename to interface/server/wgo/basicplayer.infobox.js diff --git a/interface/wgo.player-2.0/wgo/basicplayer.js b/interface/server/wgo/basicplayer.js similarity index 100% rename from interface/wgo.player-2.0/wgo/basicplayer.js rename to interface/server/wgo/basicplayer.js diff --git a/interface/wgo.player-2.0/wgo/kifu.js b/interface/server/wgo/kifu.js similarity index 100% rename from interface/wgo.player-2.0/wgo/kifu.js rename to interface/server/wgo/kifu.js diff --git a/interface/wgo.player-2.0/wgo/player.editable.js b/interface/server/wgo/player.editable.js similarity index 100% rename from interface/wgo.player-2.0/wgo/player.editable.js rename to interface/server/wgo/player.editable.js diff --git a/interface/wgo.player-2.0/wgo/player.js b/interface/server/wgo/player.js similarity index 100% rename from interface/wgo.player-2.0/wgo/player.js rename to interface/server/wgo/player.js diff --git a/interface/wgo.player-2.0/wgo/player.permalink.js b/interface/server/wgo/player.permalink.js similarity index 100% rename from interface/wgo.player-2.0/wgo/player.permalink.js rename to interface/server/wgo/player.permalink.js diff --git a/interface/wgo.player-2.0/wgo/scoremode.js b/interface/server/wgo/scoremode.js similarity index 100% rename from interface/wgo.player-2.0/wgo/scoremode.js rename to interface/server/wgo/scoremode.js diff --git a/interface/wgo.player-2.0/wgo/sgfparser.js b/interface/server/wgo/sgfparser.js similarity index 100% rename from interface/wgo.player-2.0/wgo/sgfparser.js rename to interface/server/wgo/sgfparser.js diff --git a/interface/wgo.player-2.0/wgo/wgo.js b/interface/server/wgo/wgo.js similarity index 100% rename from interface/wgo.player-2.0/wgo/wgo.js rename to interface/server/wgo/wgo.js diff --git a/interface/wgo.player-2.0/wgo/wgo.min.js b/interface/server/wgo/wgo.min.js similarity index 100% rename from interface/wgo.player-2.0/wgo/wgo.min.js rename to interface/server/wgo/wgo.min.js diff --git a/interface/wgo.player-2.0/wgo/wgo.player.css b/interface/server/wgo/wgo.player.css similarity index 100% rename from interface/wgo.player-2.0/wgo/wgo.player.css rename to interface/server/wgo/wgo.player.css diff --git a/interface/wgo.player-2.0/wgo/wgo.player.min.js b/interface/server/wgo/wgo.player.min.js similarity index 100% rename from interface/wgo.player-2.0/wgo/wgo.player.min.js rename to interface/server/wgo/wgo.player.min.js diff --git a/interface/wgo.player-2.0/wgo/wood1.jpg b/interface/server/wgo/wood1.jpg similarity index 100% rename from interface/wgo.player-2.0/wgo/wood1.jpg rename to interface/server/wgo/wood1.jpg diff --git a/interface/wgo.player-2.0/UI.html b/interface/wgo.player-2.0/UI.html deleted file mode 100644 index 66f326522..000000000 --- a/interface/wgo.player-2.0/UI.html +++ /dev/null @@ -1,26 +0,0 @@ - - - - My page - - - - - -
- Sorry, your browser doesn't support WGo.js. Download SGF directly. -
- - - - - - \ No newline at end of file