1515limitations under the License.
1616"""
1717
18- """Store and retrieve XML with App Engine.
18+ """Store and retrieve Blockly XML/JSON with App Engine.
1919"""
2020
2121__author__ = "q.neutron@gmail.com (Quynh Neutron)"
2222
23- import cgi
2423import hashlib
25- from random import randint
2624from google .cloud import ndb
25+ from random import randint
26+ from urllib .parse import unquote
2727
2828
2929class Xml (ndb .Model ):
@@ -32,6 +32,7 @@ class Xml(ndb.Model):
3232 xml_content = ndb .TextProperty ()
3333 last_accessed = ndb .DateTimeProperty (auto_now = True )
3434
35+
3536def keyGen ():
3637 # Generate a random string of length KEY_LEN.
3738 KEY_LEN = 6
@@ -40,8 +41,23 @@ def keyGen():
4041 return "" .join ([CHARS [randint (0 , max_index )] for x in range (KEY_LEN )])
4142
4243
44+ # Parse POST data (e.g. a=1&b=2) into a dictionary (e.g. {"a": 1, "b": 2}).
45+ # Very minimal parser. Does not combine repeated names (a=1&a=2), ignores
46+ # valueless names (a&b), does not support isindex or multipart/form-data.
47+ def parse_post (environ ):
48+ fp = environ ["wsgi.input" ]
49+ data = fp .read ().decode ()
50+ parts = data .split ("&" )
51+ dict = {}
52+ for part in parts :
53+ tuple = part .split ("=" , 1 )
54+ if len (tuple ) == 2 :
55+ dict [tuple [0 ]] = unquote (tuple [1 ])
56+ return dict
57+
58+
4359def xmlToKey (xml_content ):
44- # Store XML and return a generated key.
60+ # Store XML/JSON and return a generated key.
4561 xml_hash = int (hashlib .sha1 (xml_content .encode ("utf-8" )).hexdigest (), 16 )
4662 xml_hash = int (xml_hash % (2 ** 64 ) - (2 ** 63 ))
4763 client = ndb .Client ()
@@ -65,7 +81,7 @@ def xmlToKey(xml_content):
6581
6682
6783def keyToXml (key_provided ):
68- # Retrieve stored XML based on the provided key.
84+ # Retrieve stored XML/JSON based on the provided key.
6985 # Normalize the string.
7086 key_provided = key_provided .lower ().strip ()
7187 # Check datastore for a match.
@@ -91,13 +107,17 @@ def app(environ, start_response):
91107 ]
92108 if environ ["REQUEST_METHOD" ] != "POST" :
93109 start_response ("405 Method Not Allowed" , headers )
94- return ["Storage only accepts POST" .encode ('utf-8' )]
110+ return ["Storage only accepts POST" .encode ("utf-8" )]
111+ if ("CONTENT_TYPE" in environ and
112+ environ ["CONTENT_TYPE" ] != "application/x-www-form-urlencoded" ):
113+ start_response ("405 Method Not Allowed" , headers )
114+ return ["Storage only accepts application/x-www-form-urlencoded" .encode ("utf-8" )]
95115
96- forms = cgi . FieldStorage ( fp = environ [ "wsgi.input" ], environ = environ )
116+ forms = parse_post ( environ )
97117 if "xml" in forms :
98- out = xmlToKey (forms ["xml" ]. value )
118+ out = xmlToKey (forms ["xml" ])
99119 elif "key" in forms :
100- out = keyToXml (forms ["key" ]. value )
120+ out = keyToXml (forms ["key" ])
101121 else :
102122 out = ""
103123
0 commit comments