def sql_connect(): global mysql_connections #global mysql_con mysql_con_local = None #try to use only one connection if mysql_con_local == None: try: mysql_con_local = mysql.connect(cursorclass=\ mysql.cursors.DictCursor, host=db_host,\ user=db_user, passwd=db_passwd, db=db_db) except mysql.err.OperationalError: return None, None mysql_connections.append(mysql_con_local); try: ret = mysql_con_local.cursor(), mysql_con_local except: elog("MySQL connection lost; attempting to re-connect. . .") mysql_con_local = mysql.connect(cursorclass=\ mysql.cursors.DictCursor, host=db_host,\ user=db_user, passwd=db_passwd, db=db_db) ret = mysql_con_local.cursor(), mysql_con_local return ret """
def gen_realpath(self): path = files_root + "/" + rot_userid(self.userid) path = os.path.abspath(os.path.normpath(path)) replchars = "`'\"\\/^:;()[]{},"; dirpath = "" parentid = self.parentid while parentid != None and parentid != ROOT_PARENT_ID: meta = fetch_file(parentid) print("PARENTID", parentid, meta["name"]); if meta["parentid"] == parentid: elog("DATABASE CORRUPTION ERROR; fixing...") update_file(parentid, {"parentid" : ROOT_PARENT_ID}); break name = "" for c in meta["name"]: if c in replchars: name += "_" else: name += c name = name.strip() dirpath = meta["name"] + "/" + dirpath parentid = meta["parentid"] dirpath = "/" + dirpath print("FINAL DIRPATH", dirpath) path += dirpath; if not os.path.exists(path): os.makedirs(path) if mangle_file_paths: fname = key_rot(self.name) else: fname = self.name path = path + os.sep + fname path = os.path.abspath(os.path.normpath(path)) self.realpath = path;
def publicid_to_fileid(publicid): k = key_unrot(publicid) if k.count(".") != 1: elog("Folder id missing userid component: " + k + "; original: " + publicid) elog(key_unrot("2388YXX4240BF6ILF8E9GA6D1")); elog(fileid_to_publicid(1, 1)); elog(key_unrot(fileid_to_publicid(1, 1))); return None elog("publicid: " + str(publicid)) print("\n\nPUBLICID!!\n\n", publicid); userid, fileid = k.split(".") userid = int(userid, 16) fileid = int(fileid, 16) return userid, fileid
def do_GET(self, serv): qs = get_qs(serv.path) #print("userinfo!") cur, con = mysql_connect() if "accessToken" not in qs: elog("access token wasn't provided") serv.send_error(400) return token = qs["accessToken"][0] userid = do_auth(token) if (userid == None): elog("invalid access") serv.send_error(401) return cur.execute("SELECT * FROM users WHERE userid=" + estr(userid)) ret = cur.fetchone() body = json.dumps({ "username": ret["username"], "userid": rot_userid(ret["userid"]), "name_last": ret["name_last"], "name_first": ret["name_first"], "email": ret["email"], "permissions": ret["permissions"], "last_login": str(ret["last_login"]) }) body = bstr(body) serv.gen_headers("GET", len(body), json_mimetype) serv.wfile.write(body)
def base_validate(basestr, table, values, types, cols=None): maxlen = len(basestr) + len(table) + len(" ") if len(cols) != len(values): raise SQLParamError("Length of cols and values must match in sql_select"); for i, d in enumerate(values): d = str(d) #don't use estr at this point; we're just validating if type(types[i]) == type: t = types[i]() if type(t) == StrType: raise SQLParamError("Invalid SQL validator") types[i] = t if len(d) > types[i].maxlen: do_sql_error(types[i], d) if not types[i].validate(d): elog("sql validation error: type " + str(type(types[i])) + ", value: \"" + str(d) + "\"") do_sql_error(types[i], d) maxlen += types[i].maxlen + 3#'' if cols != None: for i, d in enumerate(cols): d = d.lower() if len(d) > colval.maxlen or not colval.validate(d): do_sql_error(types[i], d, [table, where]) maxlen += colval.maxlen + 5 #"''= if d in colmap and type(types[i]) != colmap[d]: raise SQLParamError(d + " should be type " + str(colmap[d])) return maxlen
def do_auth(tok): cur, con = mysql_connect() try: cur.execute("SELECT * FROM authtokens WHERE tokenid=" + estr(tok)) except db_engine.DBError: cur, con = mysql_reconnect() cur.execute("SELECT * FROM authtokens WHERE tokenid=" + estr(tok)) ret = cur.fetchone() if ret == None: elog("nonexistent access token " + str(tok)) return None if ret["type"] != toktypes["A"]: elog("invalid access token " + str(tok)) return None exprtime1 = ensure_datetime(ret["expiration"]) if exprtime1 < datetime.datetime.now(): elog("expired access token " + str(tok)) return None return ret["userid"]
def do_sql_error(t, d, extra=None): elog("Database security failure") alog("Database security failure") raise RuntimeError("Invalid data for database query: type " + str(t) + ", data: " + estr(d))
def do_param_error(str): alog("possible sql injection: \"" + str + "\"") elog("possible sql injection: \"" + str + "\"")
def errlog(msg): elog(msg)
def do_PUT(self, serv): alog("fileapi access" + serv.path) qs = get_qs(serv.path) if "accessToken" not in qs or "uploadToken" not in qs: elog("fileapi: invalid tokens") serv.send_error(400) return tok = qs["accessToken"][0] utoken = qs["uploadToken"][0] userid = do_auth(tok) if userid == None: elog("invalid authorization") serv.send_error(401) return status = UploadStatus(utoken) if status.invalid: elog("invalid upload token ", utoken) serv.send_error(401) return if "Content-Range" not in serv.headers: elog("missing header " + json.dumps(serv.headers)) serv.send_error(400) return r = serv.headers["Content-Range"].strip() if not r.startswith("bytes"): elog("malformed request 1") serv.send_error(400) return r = r[len("bytes"):].strip() r = r.split("/") if r == None or len(r) != 2: elog("malformed request 2") serv.send_error(400) return try: max_size = int(r[1]) except ValueError: elog("malformed request 3") serv.send_error(400) return r = r[0].split("-") if r == None or len(r) != 2: elog("malformed request 4") serv.send_error(400) return try: r = [int(r[0]), int(r[1])] except ValueError: elog("malformed request 4") serv.send_error(400) return if r[0] < 0 or r[1] < 0 or r[0] >= max_size or r[1] >= max_size \ or r[0] > r[1]: elog("malformed request 5") serv.send_error(400) return if status.size == -1: status.size = max_size buflen = r[1]-r[0]+1 buf = serv.rfile.read(buflen) if len(buf) != buflen: elog("malformed request 6") serv.send_error(400) return """ if not status.file_init: status.file = open(status.realpath, "wb") csize = 1024*1024*1024 ilen = math.ceil(max_size/csize); zerobuf = b""*csize; for i in range(ilen): if i == ilen-1: c = b""*(max_size%(csize+1)) else: c = zerobuf; status.file.write(c) status.file.flush() status.file.close() #""" if r[0] == 0: mode = "wb" else: mode = "ab" status.file = open(status.realpath, mode); status.file.seek(r[0]); status.file.write(buf); status.file.flush() status.file.close() status.commit() body = json.dumps({"success" : True}); body = bstr(body) serv.gen_headers("PUT", len(body), json_mimetype) serv.wfile.write(body)
def do_GET(self, serv): elog("fileapi access" + serv.path) qs = get_qs(serv.path) if "accessToken" not in qs or ("path" not in qs and "id" not in qs): serv.send_error(400) return tok = qs["accessToken"][0] userid = do_auth(tok) if userid == None: elog("Need user id") serv.send_error(401) return path = qs["path"][0] if "id" in qs: fileid = qs["id"][0] else: fileid = resolve_path(path) if fileid == None: elog("creating new file") cs = os.path.split(path) folderid = resolve_path(cs[0]) if folderid == None: elog("invalid folder " + cs[0]) serv.send_error(401); return if len(cs) == 1 or cs[1] == "": fname = cs[0] else: fname = cs[1] mime = "application/octet-stream" fileid = create_file(userid, fname, mime, folderid) meta = fetch_file(fileid); else: meta = fetch_file(fileid); if meta == None: elog("Invalid file id") serv.send_error(400) return print("\n\nFILE", meta, "\n\n") if is_folder(meta): elog("target file is a folder" + meta["name"]) serv.send_error(401) return utoken = gen_token("U", userid); ustatus = UploadStatus() ustatus.create(utoken, path, userid, fileid, meta["parentid"]) ustatus.commit() f = open(ustatus.realpath, "w"); f.close(); realpath = ustatus.realpath cur, con = mysql_connect() try: qstr = sql_update("filedata", ["diskpath"], [realpath], [sq.path], ["fileid"], [fileid], [sq.int]) except SQLParamError: do_param_error("upload start") serv.send_error(401) """ qstr = "UPDATE filedata SET " qstr += "diskpath=%s"%estr(realpath) qstr += " WHERE fileid=%d"%fileid #""" cur.execute(qstr) con.commit() body = json.dumps({"uploadToken" : utoken}); body = bstr(body) print("\nupload start result:", body, "\n\n\n") serv.gen_headers("GET", len(body), json_mimetype) serv.wfile.write(body)
def do_GET(self, serv): qs = get_qs(serv.path) if "accessToken" not in qs or ("path" not in qs and "id" not in qs): serv.send_error(400) return tok = qs["accessToken"][0] userid = do_auth(tok) if userid == None: elog("Invalid access in file api") serv.send_error(401) return if "id" in qs: folderid = publicid_to_fileid(qs["id"][0]) else: folderid = [userid, resolve_path(qs["path"][0])] if folderid == None or folderid[0] != userid: elog("Bad folder " + str(qs["id"][0]) if folderid == None else "Invalid user " + str(userid) + ", " + str(folderid)) serv.send_error(401) return folderid = folderid[1] types = [sq.int , sq.int ] cols = ["userid", "parentid"] values = [userid , folderid ] try: qstr = sql_selectall("filedata", cols, values, types) except SQLParamError: do_param_error("dirlist") serv.send_error(400) return """ qstr = "SELECT name,fileid,mimeType FROM filedata " qstr += "WHERE userid="+estr(userid) + " AND " qstr += "parentid="+estr(folderid) """ cur, con = mysql_connect() cur.execute(qstr) ret = cur.fetchall() files = [] if ret != None: for row in ret: f = {} f["name"] = row["name"] f["id"] = fileid_to_publicid(row["fileid"], userid) f["mimeType"] = row["mimeType"] f["is_dir"] = row["mimeType"] == FOLDER_MIME files.append(f) body = json.dumps({"items": files}) body = bstr(body) serv.gen_headers("GET", len(body), json_mimetype) serv.wfile.write(body)
def do_GET(self, serv): elog("fileapi access" + serv.path) qs = get_qs(serv.path) if "accessToken" not in qs or ("path" not in qs and "id" not in qs): serv.send_error(400) return tok = qs["accessToken"][0] userid = do_auth(tok) if userid == None: elog("Need user id") print("Bad auth") serv.send_error(401) return path = qs["path"][0] if "id" in qs: fileid = publicid_to_fileid(qs["id"][0]) else: fileid = urllib.unquote(path) meta = File(fileid, userid) if meta != None: print("DISKPATH", meta.diskpath) if meta == None or not os.path.exists(meta.diskpath): elog("creating new file") cs = os.path.split(path) folderid = cs[0] f = File(folderid, userid) if not os.path.exists(f.diskpath): elog("invalid folder " + f.diskpath) print("invalid folder " + f.diskpath) serv.send_error(401); return if len(cs) == 1 or cs[1] == "": fname = cs[0] else: fname = cs[1] mime = "application/octet-stream" #create empty file f = open(f.diskpath+"/"+fname, "w") f.close() meta = File(fileid, userid) if meta == None: elog("Invalid file id") serv.send_error(400) return print("\n\nFILE", meta, "\n\n") if is_folder(meta): elog("target file is a folder" + meta["name"]) serv.send_error(401) return utoken = gen_token("U", userid); ustatus = UploadStatus() #ignore fileid/parentid in upload status token ustatus.create(utoken, path, userid, fileid, -1) try: ustatus.commit() except: import traceback elog("USTATUS.COMMIT failed!") traceback.print_exc() f = open(ustatus.realpath, "w"); f.close(); realpath = ustatus.realpath body = json.dumps({"uploadToken" : utoken}); body = bstr(body) print("\nupload start result:", body, "\n\n\n") serv.gen_headers("GET", len(body), json_mimetype) serv.wfile.write(body)
def do_GET(self, serv): qs = get_qs(serv.path) if "accessToken" not in qs or ("path" not in qs and "id" not in qs): serv.send_error(400) return tok = qs["accessToken"][0] userid = do_auth(tok) if userid == None: elog("Invalid access in file api") serv.send_error(401) return if "id" in qs: path = publicid_to_fileid(qs["id"][0]) else: path = qs["path"][0] path = urllib.unquote(path).strip(); print("PATHPATH", path); dir = File(path, userid) if ".." in path: serv.send_error(401) return if not serv_all_local: prefix = files_root#+rot_userid(userid) try: os.makedirs(prefix) except FileExistsError: pass dirpath = local_to_real(path) files = [] for f in listdir(dirpath): path2 = path + os.path.sep + f file = File(path2, userid) f = {} if file == None: continue print("error!", dirpath) #if file == None: continue f["name"] = file.name f["id"] = file.id f["mimeType"] = file.mimeType f["is_dir"] = 1 if file.is_dir else 0 f["parentid"] = file.parentid files.append(f) body = jsondumps({"items": files}) body = bstr(body) serv.gen_headers("GET", len(body), json_mimetype) serv.wfile.write(body)
def __init__(self, path, userid): print(" FCLS PATH", path, userid) path = os.path.normpath(path).replace(os.path.sep, "/") diskpath = local_to_real(path) froot = local_to_real("/") if not os.path.exists(diskpath): self.bad = True return else: try: nstat = dostat(diskpath) except: self.bad = True return rootid = fileapi_db.fileid_to_publicid(userid, ROOT_PARENT_ID) if stat.S_ISDIR(nstat.st_mode): mime = FOLDER_MIME self.is_dir = True else: mime = "application/x-javascript" self.is_dir = False self.name = "" self.bad = False if not serv_all_local and not diskpath.startswith(froot): elog("Error! " + diskpath) print("Error!", diskpath, froot) self.bad = True return self.diskpath = diskpath self.mimeType = mime self.id = fileid_to_publicid(path, userid) #print("Final relative path:", path, len(froot)); oname = path while len(oname) > 0 and oname[0] in ["\\", "/"]: oname = oname[1:] name = oname[oname.rfind("/")+1:].strip() name = name.replace("/", "") if name == "": name = oname self.name = name #print("Final name:", self.name) parentpath = path[:path.rfind("/")].strip() if "/" not in path: parentpath = "/" #print("PARENT PATH", "'"+parentpath+"'", fileid_to_publicid(parentpath, userid)) if name == "/" or parentpath == "/" or parentpath == "": self.parentid = rootid else: self.parentid = fileid_to_publicid(parentpath, userid)